C++ 当访问要推入联合向量的字符串的字符时,向量中的字符串会被弄乱

C++ 当访问要推入联合向量的字符串的字符时,向量中的字符串会被弄乱,c++,string,vector,unions,C++,String,Vector,Unions,下面是一个(显示问题的简单示例): 我只是访问字符串中的第一个字符;我什么都没做!但是,如果我注释掉该行,我会得到正确的输出: test ------- test another test ------- (etc....) ------- test another test even more test test test test test test lotsa test 但是有了这句话,我。。。呃,我不知道发生了什么事。这是输出: test ------- ä7R another tes

下面是一个(显示问题的简单示例):

我只是访问字符串中的第一个字符;我什么都没做!但是,如果我注释掉该行,我会得到正确的输出:

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

代码似乎没有什么问题,但很明显我做错了什么。为什么向量会像这样被破坏,它到底是如何由于不处理字符串的第一个字符而导致的?

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

每次迭代时,字符串
s
都会被
tokens
中的新字符串替换。当
for
循环在下一次迭代中将一个新字符串分配给
s
时,允许将上一次迭代的
c_str()
无效

它能够工作的事实可能是实现的幸运运气:在引擎盖下,
s
可能从
tokens
中的条目借用了字符串的存储空间。然而,对
操作符[]
的调用可能导致它自己制作字符串的私有副本。这可以解释
c_str()
的行为差异

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

nObj.oString = new char[s.size() + 1];  // allocate the space
std::strcpy( nObj.oString, s.c_str() ); // copy in the string
现在,从技术上讲,如果它包含ASCII NUL,则不会复制整个
字符串。您的原始代码并不关心这些,我上面的建议不会改变这一点。:-)您可以在
中找到
std::strcpy()


请注意,因为您已经为自己的存储分配了
new[]
,所以在以后处理完它时,您必须记住
delete[]
,否则会出现内存泄漏。并确保您使用的是
delete[]
,而不是
delete
free()

主要问题来自您的
exec

for (string s : tokens)
{
    ObjectNative nObj;

    nObj.oString = s.c_str();
语义上,您的
标记
向量是一个副本。此外,
for(string s:tokens)
s
也是循环中的临时副本。当循环退出时,
s
将不再存在。所以当你做一些类似的事情时:

nObj.oString = s.c_str();
砰!您现在有一个悬空的
const char*
。现在您的程序有未定义的行为,因为之后您尝试在
main
中打印该堆栈。
s[0]导致任何行为差异在这一点上都是不相关的

根据您的尝试,我将采取以下措施来解决此问题:

  • 将原型更改为
    void exec(常量向量和令牌、向量和堆栈)
  • s
    修改为引用。例如,
    for(const string&s:tokens)
    。只要
    标记
    不超过
    堆栈
    ,这应该是正常的

好的,那我该怎么做呢?对不起,我是C++新手。为什么访问第一个字符会影响输出?@Doorknob:实际上,我不能100%确定为什么它会使
c_str()
无效。据介绍,
c_str()
只有通过将字符串的非常量引用传递给库函数,或调用字符串上的非常量成员(不包括
[]
和其他一些成员)才能使
c_str()
无效。@doorknold:就分配存储和复制它而言,您可以执行
char*tmp=new char[s.size()+1];std::strcpy(tmp,s.c_str())
,并将
tmp
分配给
nObj.oString
。记住以后处理完字符串后要删除[]
。@Doorknob:哦,等等,我知道字符串为什么会变得无效。它们应该只对一次迭代有效,因为
for
循环正在按顺序将
标记中的每个字符串分配给
s
。事实上,它曾经奏效是一个幸运的巧合。它可能是借用了
tokens
中字符串中的存储空间,而没有
s[0]
,但是一旦你打电话给
operator[]
,它就不得不停止借用存储空间,并制作自己的本地副本。好的,谢谢,我会试试看。如果你把它编辑成你的答案,并且它有效,我会接受它。谢谢对
标记中的字符串进行任何修改都会导致问题。如果这是一个解析器,那么这个向量可能会被回收…@joe True。在我看来,op应该避免使用原始
constchar*
。表示
对象的类型
需要更好地封装。同意。如果是我,我只会有一个<代码> STD::String ,我可能会在 Ung/<代码>上考虑多态性。
for (string s : tokens)
{
    ObjectNative nObj;

    nObj.oString = s.c_str();
nObj.oString = s.c_str();