字符串的C++向量,为什么赋值会导致相同的字符引用

C++ vector of strings, why assignment results in same char references?

本文关键字:字符 引用 赋值 向量 C++ 为什么 字符串      更新时间:2023-10-16

我目前正在学习C++,我想手动将值输入到字符串向量中,在存储每个字符之前对其进行处理。这是我使用的代码:

#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
    int i, height = 5, width = 5;
    vector<string> lab;
    lab.resize(height, "");
    string s;
    //For input reference
    cout << endl << "Input data:" << endl << "01234" << endl;
    //Input values
    for (i = 0; i < height; i++)
    {
        getline (cin, s);
        for (int j = 0; j < width; j++) 
        {   
            //Process char [...]
            lab[i][j] = s.at(j);
        }
    }
    //Show Matrix
    cout << endl << endl;
    for (int i = 0; i < height; i++)
    {   
        for (int j = 0; j < width; j++)
        {
            cout << lab[i][j] << " "; 
        }
        cout << endl;
    }
    //Show Addresses
    cout << endl << endl;
    for (int i = 0; i < height; i++)
    {   
        cout << "String Addr: " << (void*) &lab[i] << " | Chars Addr: ";
        for (int j = 0; j < width; j++)
        {
            //cout << lab[i][j] << " "; 
            cout << (void*) &lab[i][j] << " ";
        }
        cout << endl;
    }
    cout << endl;
    return 0;
}

问题是字符串中的字符有相同的地址(我不知道为什么)。以下是该程序的一个执行示例:

Input data:
01234
aaaaa
bbbbb
ccccc
ddddd
abcde
a b c d e 
a b c d e 
a b c d e 
a b c d e 
a b c d e 
String Addr: 0x8fe8008 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610 
String Addr: 0x8fe800c | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610 
String Addr: 0x8fe8010 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610 
String Addr: 0x8fe8014 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610 
String Addr: 0x8fe8018 | Chars Addr: 0xb773260c 0xb773260d 0xb773260e 0xb773260f 0xb7732610

最后,您可以看到字符的地址是相同的,而字符串的地址是不同的。示例中的最终矩阵应该是:

a a a a a
b b b b b
c c c c c
d d d d d
a b c d e

但相反,它是:

a b c d e 
a b c d e 
a b c d e 
a b c d e 
a b c d e 

虽然我已经解决了这个问题,使用+=运算符而不是使用[]赋值,但我仍然不知道上面的代码到底发生了什么。为什么这些字符有相同的引用?

你的作业越界了:

lab[i][j] = s.at(j);

lab[i]是有效的,但任何jlab[i][j]都是越界的,因为向量中的所有字符串都初始化为空字符串""

问题是,尽管调整了向量的大小,但没有调整其中的任何字符串的大小,它们仍然是零长度。所以当你做时

lab[i][j] = s.at(j);

您正在访问lab[i]处的字符串边界之外的内容。

这应该工作

    for (int j = 0; j < width; j++) 
    {   
        //Process char [...]
        lab[i].push_back(s.at(j));
    }

这个版本在处理字符串时将每个字符添加到字符串中。

此代码是无效的

//Input values
for (i = 0; i < height; i++)
{
    getline (cin, s);
    for (int j = 0; j < width; j++) 
    {   
        //Process char [...]
        lab[i][j] = s.at(j);
    }
}

向量的每个字符串都是空的,因此您可能无法通过下标运算符访问其元素。

避免处理字符串中的分隔符字符。在对字符串调用operator[]之前,您没有事件设置大小,当我使用g++/mingw检查时,它甚至不起作用。

这条线路不好:

 lab[i][j] = s.at(j);

lab[i]不是用大小构造的,因此不要求它能够包含任何内容。

使用(不带循环j):

lab[i] = s;

甚至更好:

//Input values
for (i = 0; i < height; i++)
{
    getline (cin, lab[i]);
}