vector <char>元素的打印地址显示垃圾

Pal*_*ule 21 c++ vector c++17

考虑:

#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;
}
Run Code Online (Sandbox Code Playgroud)

上面代码的示例输出是:

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
Run Code Online (Sandbox Code Playgroud)

对于每个原始数据类型,存储器位置是连续的,除了char.它在屏幕上打印一些垃圾值.

我尝试添加v.reserve(4),但输出是相同的.

Rei*_*ica 39

对于每个原始数据类型,存储器位置是连续的,除了char.它在屏幕上打印一些垃圾值.

对于两种情况,"存储器位置"以完全相同的方式是连续的.唯一的区别在于您如何显示结果.当你这样做时:

cout << "Data: " << vChar[i] << " Address:" <<  &vChar[i]  << "\n";
Run Code Online (Sandbox Code Playgroud)

你给std::operator<<(std::basic_ostream)一个char*,因为你申请&(地址的上一个)char1vector,这使得它把它作为一个C风格的字符串-这意味着,它看起来对终止空.在你的情况下,这个null确实是在一些垃圾之后.2但是你也一定会有一些垃圾vector<int>,只有你不打印它.3

如果你想获得相同的打印输出vector<int>,那么你可以显式地转换为void指针,所以std::cout将它视为要打印的地址(这里overload(7)),而不是字符串:

cout << "Data: " << vChar[i] << " Address:" <<  static_cast<void*>(&vChar[i])  << "\n";
Run Code Online (Sandbox Code Playgroud)

在这种情况下,输出是:

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
Run Code Online (Sandbox Code Playgroud)

1 char&准确地说,作为std::vector<T>::operator[]返回a T&.

2请注意,查找未放置在此处的此终止空值会构成未定义的行为,因为它可能会使您访问不打算为此目的访问的内存.

3呦可以试试,看看这样的自己,如果你执行反向铸造,使std::cout治疗vector<int>的元素为C风格的字符串:

cout << "Data: " << vInt[i] << " Address:" << reinterpret_cast<char*>(&vInt[i]) << "\n";
Run Code Online (Sandbox Code Playgroud)

再次,只记住这意味着未定义的行为,因为打印代码将在内存中查找终止null,而你肯定没有它在那里找到它.


Dev*_*ull 8

std::vector<T>::operator[]()返回T&,其中的地址char将由重载(2)格式化,operator<<(std::basic_ostream)就好像它是一个空终止的C风格的字符串(这是一个字符串,从&vChar[i]第一个\0找到并在第一个找到时停止).

使其工作用于std::cout << static_cast<const void*>(&vChar[i])拾取过载(7)std::basic_ostream::operator<<().