在第2步中,我只更改name_C
的值。为什么name_B
也会发生变化?
以下是代码:
#include <cstdlib>
#include <dirent.h>
#include <iostream>
#include <fstream>
#include <direct.h>
using namespace std;
int main(int argc, char *argv[])
{
// step 1
char *name_A;
char *name_B;
char *name_C;
string str_L = "hello";
string str_M = "stringVar_A"; ;
name_A = (char *) str_M.c_str();
name_B = (char *) (str_L + "-car-" + str_M).c_str();
name_C = (char *) str_L.c_str();
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl;
cout << " name_C= " << name_C << endl << endl << endl;
// step 2
string str_N = "myStringMyString"; // (in my real code, i can't put this line in step 1)
string str_R = "ABCDEFGHI" + str_N; // (in my real code, i can't put this line in step 1)
name_C = (char *)str_R.c_str(); // change only name_C
cout << " name_A= " << name_A << endl;
cout << " name_B= " << name_B << endl; // changed, why?
cout << " name_C= " << name_C << endl; // changed, ok.
system("PAUSE");
return EXIT_SUCCESS;
};
这里输出:
(step 1:)
name_A= stringVar_A
name_B= hello-car-stringVar_A
name_C= hello
(step 2:)
name_A= stringVar_A
name_B= ABCDEFGHImyStringMyString
name_C= ABCDEFGHImyStringMyString
使用:
string str_N = "myString"; // in step 2...
name_B
不会改变
如果name_B
超过10个字母,为什么str_N
会发生变化?
有人能帮我理解这种行为吗?
答案 0 :(得分:4)
只要相应的c_str
停留在范围内且未经修改,对std::string
的调用返回的指针仅有效。
除此之外访问它的行为是未定义的。
例如,(str_L + "-car-" + str_M).c_str();
正在向您返回匿名临时的c_str
。分配后它将立即失效。在您的情况下,name_B
无效。
另外,请勿丢弃const char*
c_str()
次的回复。它的const
有一个很好的理由:你不应该尝试通过该指针修改字符串内容。
答案 1 :(得分:3)
您正在导致未定义的行为。
name_B = (char *) (str_L + "-car-" + str_M).c_str();
你从std :: string :: operator +的结果创建一个temoprary字符串,从中提取C字符数组,但是没有人真正捕获临时字符串。
当一个临时没有被const引用捕获时 - 它立即被销毁。字符串析构函数取消分配内部字符数组并使name_B无效。
所以,这是未定义的行为,因为您尝试使用不再有效的内存地址。
答案 2 :(得分:2)
std::string::c_str()
返回指向std::string
的内部缓冲区的指针,并保证:
c_str()
; c_str() + size()
]有效。在您的情况下,name_B
指向临时对象name_B = (str_L + "-car-" + str_M).c_str();
的内部缓冲区,当您尝试使用它时,将导致未定义的行为。<登记/>
当您对堆栈进行一些修改(定义两个新的std::string
)时,您可能会改变name_B
指向的堆栈位置(因为临时保留的内存已被释放)。 / p>
如果您真的必须从std::string
获取旧式C字符串,请确保:
std::string::c_str()
时,不再使用从std::string
检索到的指针,std::string::c_str()
。