C++字符串字面量有多安全可靠?

8

所以,我想更好地了解C++中字符串字面值的工作原理。我主要关心的是当您将字符串字面值的地址分配给指针并传递它时的情况。例如:

char* advice = "Don't stick your hands in the toaster.";

现在假设我只是通过复制指针来传递这个字符串,整个程序的时间。当然,这可能不是一个好主意,但我很好奇背后实际发生了什么。
另一个例子,假设我们创建一个返回字符串文字的函数:
char* foo()
{
    // function does does stuff
    return "Yikes!"; // somebody's feeble attempt at an error message
}

现在假设这个函数被频繁调用,而字符串字面量只有一半的时间被使用:
// situation #1: it's just randomly called without heed to the return value
foo(); 

// situation #2: the returned string is kept and used for who knows how long
char* retVal = foo();

在第一种情况下,实际上发生了什么?字符串只是被创建但没有使用,并且从未被释放吗?
在第二种情况下,字符串会在用户需要它的时候维护多长时间?当它不再需要时会发生什么...假设没有任何指向该空间的东西,那么内存是否会被释放?
别误会,我不打算像这样使用字符串字面量。我计划使用容器来控制我的字符串(可能是std::string)。我主要想知道这些情况是否会对内存管理或损坏数据造成问题。

9
C++ 字符串字面量非常安全可靠。问题在于使用字符串字面量的程序员可能不够安全和可靠。 - John Dibling
这就是我所思考的,我只是需要一些确认。谢谢。 :) - Tim Leaf
2个回答

25

字符串字面值的类型是const char[N](其中N是长度+1),并且是静态分配的。您不必担心内存问题;如果在程序中使用字符串,所有处理都已为您处理,并且该字符串位于程序内存中的某个位置(通常为只读)。

也就是说,以下内容“相同”:

static const char str[] = "a string";
"a string"

当你指向一个字符串字面量时,实际上你是指向数组中的第一个字符。事实上,由于类型是const char[],因此只能通过const char*安全地指向它。从字符串字面量到char*的转换已被弃用,并且是不安全的。

// the "same"
static const char str[] = "a string";
const char* strPtr = str; // decays

const char* s1 = "a string";
char* s2 = "a string"; // allowed, implicit const_cast

*s1 = 'A'; // not allowed, it's const
*s2 = 'B'; // allowed, it's not const (but leads to undefined behavior)

5
字符串字面值转换为char*已经被弃用且不安全。如果您曾经这样做过,需要使用“-fwritable-strings”选项。无论如何,请勿这样做。 - Joshua
2
据我所知,你已经说了所有的话。 - John Dibling
1
唯一需要注意的是编译器允许字符串池化,因此在前面的例子中 &str[0]s1 可能指向相同的内存。通常这不会成为问题,除非你故意修改只读字符串。 - D.Shawley
1
@GManNickG char* s2 = "a string"; // allowed, implicit const_cast. 并不存在从const到non-const的隐式const_cast!此外,字符串字面值的类型是const char const *,因为指针和内容在整个程序执行期间都是常量。 - Gold
1
@GManNickG:我认为这就是重点,即隐式转换已从C++中移除,导致该代码不再编译。 - Mooing Duck
显示剩余2条评论

1
首先,将foo的返回值声明为const,因为字符串字面量是常量,不能在不引起可怕的“未定义行为”的情况下更改。这将强制使用foo的返回值的任何指针也被声明为const,并且可能限制可以(通常是无意中)造成的损害。字符串字面量存储在二进制可执行文件的“文本”区域中 - 它们不是在运行时创建的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接