【问题标题】:C++ '+' concatenation operator changing contents of pointers in pointer vectorC ++'+'连接运算符更改指针向量中指针的内容
【发布时间】:2021-05-31 22:04:32
【问题描述】:

所以我想编写一个执行以下操作的程序:

  • 使用 std::getline(std::cin,str) 接受用户输入的字符串
  • 使用+ 运算符将此输入附加到std::string object
  • object 的初始值为object="\n"
  • 用户输入一行并附加到 object 后,将 '\n' 添加到对象
  • 例如,如果在控制台中输入hello,则object="\nhello\n"
  • 如果在下一行输入my,则输入object="\nhello\nmy\n",以此类推。

现在我还声明了一个std::vector<const char*> lines,它指向object 中的所有\n 字符

在我们以最后一个要点给出的例子中,lines 有 3 个元素指向 \n 字符

代码如下:

#include <iostream>
#include <string>
#include <vector>
int main()
{
    std::vector<const char*> lines;
    std::string object = "\n";
    lines.push_back(object.c_str());
    std::string temp;
    int object_size;
    while (std::getline(std::cin,temp))
    {
        object_size = object.length();
        object = object + temp;
        object = object + "\n";
        lines.push_back(object.c_str() + object_size + temp.size());//pointers in this point to all the \n characters

    }

}

现在问题来了:

所以输入后

hello
name
is

并在vs 2019集成调试器的监视窗口中检查行和对象的值,它显示

object="\nhello\nname\nis\n"
lines[0]=0x0082fb04"\nhello\nname\nis\n"                \\points to first \n
lines[1]=0x0082fb0a"\nname\nis\n"                        \\points to second \n
lines[2]=0x0082fb0f"\nis\n"                               \\points to third \n
lines[3]=0x0082fb12"\n"                                    \\points to last \n

这是有道理的,因为object 中有 4 个\n

现在我在下一行输入xyzabc,所以控制台看起来像:

hello
name
is
xyzabc

在while循环中,一切都很好,直到该行 object=object+temp;

object=object+temp;一执行,调试器就会显示:

object="\nhello\nname\nis\nxyzabc"       \\object does not end with \n because object = object + "\n" has not been executed yet
lines[0]=0x0082fb04 "pù\x4\x1lo\nname\nis"
lines[1]=0x0082fb0a "\nname\nis"
lines[2]=0x0082fb1f "\nis"
lines[3]=0x0082fb12""    

object 的值符合预期,但 lines 中的指针指向的内容已被 object=object+temp 行修改 执行该行后的预期值为:

object="\nhello\nname\nis\nxyzabc"
lines[0]=0x0082fb04"\nhello\nname\nis\nxyzabc"                
lines[1]=0x0082fb0a"\nname\nis\nxyzabc"                        
lines[2]=0x0082fb0f"\nis\nxyzabc"                               
lines[3]=0x0082fb12"\nxyzabc"                                    

为什么会这样?以及如何附加我objecttemp 而不会遇到这个问题?

【问题讨论】:

  • 当你扩展你的字符串时,它可能需要重新定位数据。所有迭代器(和你的指针)然后变得无效。存储索引而不是指针。

标签: c++ string pointers vector c-strings


【解决方案1】:

object + temp;object + "\n"; 都很好,并且做正确的事:连接字符串。但是,这是不正确的:

lines.push_back(object.c_str() + object_size + temp.size());

因为 (cppreference::string::c_str)...

返回指向带有数据的以空字符结尾的字符数组的指针 相当于存储在字符串中的那些。

指针使得范围 [c_str(); c_str() + size()] 是 有效并且其中的值对应于存储在 在最后一个位置后带有一个额外的空字符的字符串。

从 c_str() 中获得的指针可能会通过以下方式失效:

  • 将对字符串的非常量引用传递给任何标准库函数,或者
  • 在字符串上调用非常量成员函数,不包括 operator[]、at()、front()、back()、begin()、rbegin()、end() 和 撕裂()。

c_str 返回的指针并不意味着独立于字符串存储。如果你想在向量中存储字符串(而不是无效指针),你应该使用std::vector&lt;std::string&gt;

【讨论】:

    【解决方案2】:

    object 可能会在您将内容连接到其中时被重新分配。这意味着在lines 中指向其内容的指针无效。这是未定义的行为。

    【讨论】:

    • 那么有什么方法可以将其他字符串连接到对象中而不必面对这个问题,谢谢。
    • @SwarajSonavane 存储索引而不是指针。
    • 对不起,我是初学者,我不确定您所说的“索引”是什么意思
    • 存储字符串中\n的位置,而不是指针。
    • 另外,您不能将每一行单独存储在std::vector&lt;std::string&gt; lines; 中并继续使用吗?或者您是否特别需要 1 个单一的 std::string 缓冲区来连续存储所有内容?
    猜你喜欢
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 2019-09-10
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    相关资源
    最近更新 更多