web-dev-qa-db-ja.com

vector <char>の要素のアドレスを印刷するとゴミが表示される

考慮してください:

#include <vector>
#include <string>
#include <iostream>
using namespace std;

int main()
{
    vector<char> vChar;
    vChar.Push_back('a');
    vChar.Push_back('b');
    vChar.Push_back('c');
    vChar.Push_back('d');

    vector<int> vInt;
    vInt.Push_back(1);
    vInt.Push_back(2);
    vInt.Push_back(3);
    vInt.Push_back(4);

    cout << "For char vector Size:" << vChar.size() << " Capacity:" << vChar.capacity() << "\n";
    for(int i=0; i < vChar.size(); i++)
    {
        cout << "Data: " << vChar[i] << " Address:" <<  &vChar[i]  << "\n";
    }

    cout << "\nFor int vector Size:" << vInt.size() << " Capacity:" << vInt.capacity() << "\n";
    for (int i = 0; i < vInt.size(); i++)
    {
        cout << "Data: " << vInt[i] << " Address:" << &vInt[i] << "\n";
    }

    return 0;
}

上記のコードのサンプル出力は次のとおりです。

For char vector Size:4 Capacity:4
Data: a Address:abcd²²²²αPⁿ▀┬
Data: b Address:bcd²²²²αPⁿ▀┬
Data: c Address:cd²²²²αPⁿ▀┬
Data: d Address:d²²²²αPⁿ▀┬

For int vector Size:4 Capacity:4
Data: 1 Address:000001F020F80420
Data: 2 Address:000001F020F80424
Data: 3 Address:000001F020F80428
Data: 4 Address:000001F020F8042C

すべてのプリミティブデータタイプについて、charを除き、メモリロケーションは連続しています。画面にゴミ値を出力します。

V.reserve(4)を追加しようとしましたが、出力は同じでした。

21
Palash Tichkule

プリミティブデータタイプごとに、charを除き、メモリロケーションは連続しています。画面にゴミ値を出力します。

「メモリの場所」は、どちらの場合もまったく同じように連続しています。唯一の違いは、結果の表示方法です。あなたがするとき:

_cout << "Data: " << vChar[i] << " Address:" <<  &vChar[i]  << "\n";
_

std::operator<<(std::basic_ostream) に_char*_を与えているのは、_&_(address-of)を単一のchar1 vectorから、これをCスタイルの文字列として処理します。つまり、終端のnullを探します。あなたの場合、このnullは確かにゴミの直後です。2 しかし、あなたは_vector<int>_の後にもゴミを持っているに違いありません、あなただけがそれを印刷していません。3

_vector<int>_の場合と同じ印刷結果を取得したい場合は、明示的にvoidポインターにキャストできます。そのため、_std::cout_はそれをアドレスとして扱います印刷( ここではオーバーロード(7) )、文字列ではない:

_cout << "Data: " << vChar[i] << " Address:" <<  static_cast<void*>(&vChar[i])  << "\n";
_

その場合、出力は次のとおりです。

_For char vector Size:4 Capacity:4
Data: a Address:0x1c39810
Data: b Address:0x1c39811
Data: c Address:0x1c39812
Data: d Address:0x1c39813

For int vector Size:4 Capacity:4
Data: 1 Address:0x1c39960
Data: 2 Address:0x1c39964
Data: 3 Address:0x1c39968
Data: 4 Address:0x1c3996c
_

1 _char&_は正確に言うと、_std::vector<T>::operator[]_が_T&_を返すためです。

2 これを探す終端nullは、あなたによってそこに置かれなかったものであることに注意してください未定義の動作。これは、このためにアクセスされることを意図していないメモリにアクセスする可能性があるためです目的。

3 _std::cout_が_vector<int>_要素をCスタイルの文字列として扱うように逆キャストを実行する場合は、自分で試してみることができます。

_cout << "Data: " << vInt[i] << " Address:" << reinterpret_cast<char*>(&vInt[i]) << "\n";
_

繰り返しますが、これは未定義の動作を意味することを覚えておいてください。印刷コードはメモリ内で終端のnullを検索します。

39

std::vector<T>::operator[]()は_T&_を返します。charの場合、そのアドレスは operator<<(std::basic_ostream) asのオーバーロード(2)によってフォーマットされますnullで終了したCスタイルの文字列(_&vChar[i]_で始まり、最初に見つかった_\0_で終わる文字列)の場合.

動作させるには、std::cout << static_cast<const void*>(&vChar[i])を使用して std::basic_ostream::operator<<() のオーバーロード(7)を取得します。

8
Dev Null