49

Herb Sutter 在 2008 年在他的网站上发表的一篇文章中说:

出于与并发相关的原因,有一个积极的提议要在 C++0x 中进一步加强这一点,并要求空终止并可能禁止写时复制实现。这是论文:http ://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2534.html 。我认为本文中的一项或两项提案很可能会被采纳,但我们将在下一次或两次会议上看到。

我知道 C++11 现在保证 std::string 内容连续存储,但是他们在最终草案中采用了上述内容吗?

现在使用类似的东西安全&str[0]吗?

4

3 回答 3

53

是的。根据 C++0x FDIS 21.4.7.1/1,std::basic_string::c_str()必须返回

一个指针p,使得p + i == &operator[](i)对于每个iin [0,size()]

这意味着给定一个 string s,返回的指针s.c_str()必须与 string ( &s[0]) 中初始字符的地址相同。

于 2011-05-20T20:30:25.400 回答
-2

&str[0]使用是安全的——只要你不认为它指向一个以 null 结尾的字符串。

自 C++11 起,要求包括([string.accessors] 部分):

  • str.data()str.c_str()指向一个以 null 结尾的字符串。
  • &str[i]== str.data() + i , 对于0 <= i <= str.size()
    • 请注意,这意味着存储是连续的。

但是,没有要求&str[0] + str.size()指向空终止符。

当调用或时data(),符合要求的实现必须将空终止符连续放置在存储中;但是没有要求将它放在任何其他情况下,例如使用其他参数调用。c_str()operator[](str.size())operator[]


为了节省您阅读下面冗长的聊天讨论的时间: 有人提出了反对意见,即如果c_str()要编写空终止符,则会导致res.on.data.races#3下的数据竞争 ;我不同意这将是一场数据竞赛。

于 2021-06-11T13:14:59.010 回答
-3

尽管 c_str() 返回 std::string 的空终止版本,但将 C++ std::string 与 C char* 字符串混合时可能会出现意外。

空字符可能会出现在 C++ std::string 中,这可能会导致细微的错误,因为 C 函数会看到更短的字符串。

错误代码可能会覆盖空终止符。这会导致未定义的行为。然后,C 函数将读取字符串缓冲区之外的内容,从而可能导致崩溃。

#include <string>
#include <iostream>
#include <cstdio>
#include <cstring>

int main()
{
    std::string embedded_null = "hello\n";
    embedded_null += '\0';
    embedded_null += "world\n";

    // C string functions finish early at embedded \0
    std::cout << "C++ size: " << embedded_null.size() 
              << " value: " << embedded_null;
    printf("C strlen: %d value: %s\n", 
           strlen(embedded_null.c_str()), 
           embedded_null.c_str());

    std::string missing_terminator(3, 'n');
    missing_terminator[3] = 'a'; // BUG: Undefined behaviour

    // C string functions read beyond buffer and may crash
    std::cout << "C++ size: " << missing_terminator.size() 
              << " value: " << missing_terminator << '\n';
    printf("C strlen: %d value: %s\n", 
           strlen(missing_terminator.c_str()), 
           missing_terminator.c_str());
}

输出:

$ c++ example.cpp
$ ./a.out
C++ size: 13 value: hello
world
C strlen: 6 value: hello

C++ size: 3 value: nnn
C strlen: 6 value: nnna�
于 2021-04-22T22:04:47.350 回答