c++ - 当访问要插入 union vector 中的字符串字符时, vector 中的字符串会变得困惑

标签 c++ string vector unions

这是一个SSCCE (简单的例子来说明问题):

#include <iostream>
#include <string>
#include <vector>
using namespace std;

enum Type {oInt, oFloat, oString, oArray};

struct Object; // fwd decl for union
union ObjectNative {
    int oInt;
    float oFloat;
    const char* oString;
    vector<Object>* oArray;
};
struct Object {
    Type type;
    ObjectNative obj;
};

vector<Object> exec(vector<string> tokens, vector<Object> stack);
void printStack(vector<Object> stack);

int main() {
    vector<string> tokens{"test", "another test", "even more test", "test test", "test test test", "lotsa test"};
    vector<Object> stack;
    stack = exec(tokens, stack);
    printStack(stack);

    return 0;
}

vector<Object> exec(vector<string> tokens, vector<Object> stack) {
    for (string s : tokens) {
        ObjectNative nObj;

        // !!!!!!!!!!!!!!!!!!!!!! THIS LINE !!!!!!!!!!!!!!!!!!!!!!
        s[0];

        nObj.oString = s.c_str();
        Object obj = Object{oString, nObj};
        stack.push_back(obj);

        // debugging lines
        printStack(stack);
        cout << "-------" << endl;
    }
    return stack;
}

void printStack(vector<Object> stack) {
    for (unsigned int i = 0; i < stack.size(); i ++) {
        Object o = stack[i];
        cout << o.obj.oString;
        cout << endl;
    }
}

注意我在 exec 函数中标记的行:

s[0];

我只是访问字符串中的第一个字符;我什至没有用它做任何事!但是,如果我注释掉该行,我会得到正确的输出:

test
-------
test
another test
-------
(etc....)
-------
test
another test
even more test
test test
test test test
lotsa test

但是有了那句话,我...呃,我不确定发生了什么。这是输出:

test
-------
ä7R
another test
-------
ä7R
even more test
even more test
-------
test test
ä7R
ä7R
test test
-------
test test
test test test
test test test
test test
test test test
-------
lotsa test
ä7R
ä7R
lotsa test
ä7R
lotsa test
-------
lotsa test
ä7R
ä7R
lotsa test
ä7R
lotsa test

看起来代码没有任何问题,但显然我做的事情非常错误。为什么 vector 会被这样损坏,它到底是如何因对字符串的第一个字符不执行任何操作而导致的?

最佳答案

const char * 的生命周期返回者 string::c_str()是有限的。如果您想保留这些字符串,则需要将它们复制到专用存储中。

字符串stokens 中的新字符串替换在每次迭代中。当 for循环将一个新字符串分配给 s在下一次迭代中,允许使 c_str() 无效。来自上一次迭代的结果。

事实上,它能起作用可能是实现的幸运侥幸:在幕后,s可能从 tokens 中的条目借用了字符串的存储空间。 。调用operator[]然而,可能导致它制作自己的字符串的私有(private)拷贝。这可以解释 c_str() 的行为差异。 .

要将拷贝保存在专用存储中,您需要为其分配空间并将字符串复制到其中。像下面这样的代码就足够了:

nObj.oString = new char[s.size() + 1];  // allocate the space
std::strcpy( nObj.oString, s.c_str() ); // copy in the string

现在,从技术上讲,这不会复制整个 string如果它包含 ASCII NUL。您的原始代码并不关心这些,我上面的建议也不会改变这一点。 :-) 你可以找到std::strcpy()<cstring> .

请注意,因为您已使用 new[] 分配了自己的存储空间,你必须记住delete[]等你用完之后再做,否则会出现内存泄漏。并确保您使用 delete[] ,不是deletefree() .

关于c++ - 当访问要插入 union vector 中的字符串字符时, vector 中的字符串会变得困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20534016/

相关文章:

c++ - 当可以返回错误/异常时,从库中终止调用程序(例如,调用 exit())总是错误的吗?

c++ - 在 Netbeans 7.0 中包含 C++ 库

c++ - 正确扩展 COM 接口(interface) (IDL)

c - 从 C 文件中排序单词和数字

javascript - 在javascript中实现一个将对象转换为字符串的递归函数

java - 数组中同一索引有两个值

c++ - 在多个 Cpp 文件中使用一个变量

c++ - 在标准 C++ 中创建动态位​​集?

c# - 我可以使用 LINQ 将两个数组的值相加吗?

image - MATLAB:层检测,矢量组合和曲折/弧长选择