使用表达式初始化 char * 不起作用

Initializing a char * with an expression does not work

以下代码产生了错误的输出:

string my_string="My_First_Text";
char * my_pointer=(char *)(my_string+"My_Second_Text").c_str();

为什么?当我初始化 my_pointer 时,我假设不需要 my_pointer=new char[100]。如果这个假设不成立,那为什么呢?

注意my_string+"My_Second_Text"是一个临时的std::string,表达式后会立即销毁。这意味着 my_pointer 将立即悬空,因为它应该指向的字符数组已随着临时 std::string 的销毁而被销毁;请注意,returned 字符数组属于 std::string,它不是独立的。然后,对悬挂指针的尊重将导致 UB。

string my_string="My_First_Text";
char * my_pointer=(char *)(my_string+"My_Second_Text").c_str();
// the temporary constructed from my_string+"My_Second_Text" has been destroyed
// my_pointer is dangled now; deference on it is UB

使用命名变量而不是临时变量就可以了。例如

string my_string = "My_First_Text";
my_string += "My_Second_Text";
const char * my_pointer = my_string.c_str();

顺便说一句:std::basic_string::c_str的return类型是const char*,任何修改都是UB。因此,尝试将其显式转换为 char* 是危险的。

Writing to the character array accessed through c_str() is undefined behavior.

除了将 c_str (const char*) 转换为 char* 之外,这不是一个好主意,"my_pointer" 是使用临时对象初始化的,并被销毁在计算表达式之后。意思是,就在最后一个';'之后在你的代码中。
这意味着 my_pointer 指向不再有效的内存,并且会产生意外结果。

您的代码有未定义的行为。 + 运算符 return 一个新的临时字符串对象,它将在 (my_string+"My_Second_Text").c_str() 表达式之外被销毁,因此对该字符串的任何引用都将悬挂并且通过它们进行访问具有未定义的行为。

c_str() return 指向 string 的内部字符数组的 const 指针。您不能也不能通过该指针操纵 string

(my_string+"My_Second_Text") 的结果存储在新变量中或使用 append 函数将新字符串附加到现有字符串对象。

std::string new_string = my_string + "My_Second_Text";
const char* char_pointer = new_string.c_str();

my_string.append("My_Second_Text");
const char* char_pointer = my_string.c_str();

(my_string+"My_Second_Text").c_str()是一个临时值,会在程序运行时动态创建和销毁,不会保存在内存中。

指向它会导致未定义的行为,因为指向的内存未定义。使用 strcpy 或变量赋值,而不是将字符串赋值给 char *.

的临时值

临时对象 会导致难以理解的问题。

Bjarne 的 C++ 书籍的相关摘录:

void f(string& s1, string& s2, string& s3)
{
  const char∗ cs = (s1+s2).c_str();  // << Code similar to OP's example
  cout << cs;
  if (strlen(cs=(s2+s3).c_str())<8 && cs[0]=='a') {
  // cs used here
  }
}

Probably, your first reaction is ‘‘But don’t do that!’’ and I agree. However, such code does get written, so it is worth knowing how it is interpreted.

A temporary string object is created to hold s1 + s2. Next, a pointer to a C-style string is extracted from that object. Then – at the end of the expression – the temporary object is deleted. However, the C-style string returned by c_str() was allocated as part of the temporary object holding s1 + s2, and that storage is not guaranteed to exist after that temporary is destroyed. Consequently, cs points to deallocated storage.

The output operation cout << cs might work as expected, but that would be sheer luck. A compiler can detect and warn against many variants of this problem.

附带说明,在 C++ 中使用适当的强制转换而不是 C-style 强制转换。阅读

When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?