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

时间:2018-09-19 05:10:40

标签: 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;
}

上面的代码的示例输出是:

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

2 个答案:

答案 0 :(得分:38)

  

对于每种原始数据类型,内存位置是连续的,除了    <?php $array = Array ( "100" => Array ( "class 1" => Array ( "0" => "ABC", "1" => "CDE" ), "class 2" => Array ( "0" => "F" ) ), "200" => Array ( "class 3" => Array ( "0" => "G" ) ) ); foreach($array as $firstKey => $firstVal){ $mainArray[] = $firstKey; foreach($firstVal as $secondKey => $secondVal){ foreach($secondVal as $thiredKey => $thiredVal){ $mainArray[] = $thiredVal; } } } echo "<pre>"; print_r($mainArray); ?> 。它在屏幕上打印一些垃圾值。

对于两种情况,“内存位置”是完全相同的。唯一的区别在于您如何显示结果。当您这样做时:

char

当您在单个cout << "Data: " << vChar[i] << " Address:" << &vChar[i] << "\n"; 上应用char*地址)时,您正在给std::operator<<(std::basic_ostream)一个& char中的sup> 1 ,这使其将其视为C样式的字符串-表示,它将查找终止null 。在您的情况下,此 null 确实在一些垃圾之后。 2 但是,您也一定会在vector之后有一些垃圾,只有您自己'不打印。 3

如果要获得与vector<int>相同的打印输出,则可以显式转换为vector<int>指针,因此void会将其视为地址要打印(overload (7) here),而不是字符串:

std::cout

在这种情况下,输出为:

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

1 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 准确地说,因为char&返回了std::vector<T>::operator[]

2 注意,寻找未被您放置的终止空会构成未定义行为,因为它可能使您访问不能用于此目的的内存。

3 如果您执行反向强制转换以使T&std::cout元素视为C风格的字符串,您可以尝试自己看一下:

vector<int>

再次,只记得这意味着未定义的行为,因为打印代码将在内存中查找终止的空值,而您肯定没有找到它的地方。

答案 1 :(得分:8)

std::vector<T>::operator[]()返回T&,在char的情况下,其地址将通过operator<<(std::basic_ostream)的重载(2)进行格式化,就好像它是一个空终止的C样式字符串(即从&vChar[i]开始到找到的第一个\0结束的字符串)。

要使其正常工作,请使用std::cout << static_cast<const void*>(&vChar[i])来拾取std::basic_ostream::operator<<()的重载(7)。