webentwicklung-frage-antwort-db.com.de

Das Drucken von Adressen von Elementen des Vektors <char> zeigt Müll

Erwägen:

#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;
}

Beispielausgabe für den obigen Code ist:

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

Für jeden primitiven Datentyp sind Speicherplätze mit Ausnahme von char zusammenhängend. Es wird ein Müllwert auf dem Bildschirm ausgegeben.

Ich habe versucht, v.reserve (4) hinzuzufügen, aber die Ausgabe war dieselbe.

21
Palash Tichkule

Für jeden primitiven Datentyp sind die Speicherorte mit Ausnahme von char zusammenhängend. Es wird ein Müllwert auf dem Bildschirm ausgegeben.

Die "Speicherplätze" sind in beiden Fällen exakt gleich zusammenhängend. Der einzige Unterschied besteht darin, wie Sie Ihre Ergebnisse anzeigen. Wenn Sie das tun:

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

sie geben std::operator<<(std::basic_ostream) a char* an, während Sie & ( address-of ) auf einem einzelnen char1 aus dem vector, wodurch es als C-Zeichenfolge behandelt wird - das heißt, es wird nach einer endenden Null gesucht . In Ihrem Fall ist diese Null gleich nach etwas Müll in der Tat.2 Aber Sie müssen nach dem vector<int> Auch ein bisschen Müll haben, nur dass Sie ihn nicht drucken.3

Wenn Sie den gleichen Ausdruck erhalten möchten, den Sie für den vector<int> Erhalten, können Sie explizit einen void -Zeiger verwenden, sodass std::cout Ihn als Adresse behandelt zu drucken ( Überladung (7) hier ), keine Zeichenfolge:

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

In diesem Fall lautet die Ausgabe:

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& Um genau zu sein, da std::vector<T>::operator[] Einen T& Zurückgibt.

2 Beachten Sie, dass das Suchen nach dieser Null , die nicht von Ihnen dort platziert wurde, ein undefiniertes Verhalten darstellt , da Sie möglicherweise auf Speicher zugreifen, auf den zu diesem Zweck nicht zugegriffen werden soll.

3 Sie können dies selbst überprüfen, wenn Sie das umgekehrte Casting ausführen, damit std::cout Die vector<int> - Elemente als Zeichenfolgen im C-Stil behandelt werden:

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

Denken Sie auch hier daran, dies bedeutet undefiniertes Verhalten , da der Druckcode im Speicher nach der abschließenden Null sucht, während Sie ihn definitiv nicht dafür hatten finden.

39

std::vector<T>::operator[]() gibt T& zurück, dessen Adresse im Falle von char durch Überladung (2) von operator<<(std::basic_ostream) formatiert wird als wäre es eine nullterminierte C-Zeichenkette (das ist eine Zeichenkette, die bei &vChar[i] beginnt und bei der ersten gefundenen \0 endet).

Um es zum Laufen zu bringen, benutze std::cout << static_cast<const void*>(&vChar[i]), um die Überladung (7) von std::basic_ostream::operator<<() aufzunehmen.

8
Dev Null