【问题标题】:Printing addresses of vector<char>'s elements shows garbage [duplicate]矢量<char>元素的打印地址显示垃圾[重复]
【发布时间】:2018-09-19 05:10:39
【问题描述】:

考虑:

#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),但输出相同。

【问题讨论】:

    标签: c++ vector c++17


    【解决方案1】:

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

    对于这两种情况,“内存位置”以完全相同的方式连续。唯一的区别在于您显示结果的方式。当你这样做时:

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

    你给std::operator&lt;&lt;(std::basic_ostream)一个char*,因为你在一个char1上应用&amp;(地址) vector,这使它将其视为 C 风格的字符串——意思是,它寻找一个 终止的 null。在你的情况下,这个 null 确实是在一些垃圾之后。2 但是你一定会在 vector&lt;int&gt; 之后也有一些垃圾,只有你不打印。3

    如果您想获得与 vector&lt;int&gt; 相同的打印输出,则可以显式转换为 void 指针,因此 std::cout 会将其视为要打印的地址 (@987654322 @),而不是字符串:

    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&amp;,因为std::vector&lt;T&gt;::operator[] 返回一个T&amp;。

    2 请注意,查找不是您放置的 terminating null 构成未定义的行为,因为它可能使您访问不打算为此目的访问的内存。

    3 如果您执行反向转换以使 std::cout 将 vector&lt;int&gt; 元素视为 C 样式字符串,您可以尝试自己查看:

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

    同样,请记住这意味着 未定义的行为,因为打印代码会在内存中查找终止的 null,而您肯定没有它可以找到。

    【讨论】:

      【解决方案2】:

      std::vector&lt;T&gt;::operator[]() 返回T&amp;,其地址在char 的情况下将被operator&lt;&lt;(std::basic_ostream) 的重载(2) 格式化,就好像它是一个以空结尾的C 样式字符串(即开头的字符串)在&amp;vChar[i] 并在找到的第一个\0 处停止)。

      要使其正常工作,请使用 std::cout &lt;&lt; static_cast&lt;const void*&gt;(&amp;vChar[i]) 获取 std::basic_ostream::operator&lt;&lt;() 的过载 (7)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-09
        • 1970-01-01
        • 1970-01-01
        • 2017-03-14
        • 2019-11-26
        • 2018-05-11
        相关资源
        最近更新 更多