当我阅读 nVidia CUDA 源代码时,我偶然发现了这两行:
std::string stdDevString;
stdDevString = std::string(device_string);
Run Code Online (Sandbox Code Playgroud)
请注意,device_string 是一个 char[1024]。问题是:为什么构造一个空的 std::string,然后用 C 字符串作为参数再次构造它?他们为什么不只打std::string stdDevString = std::string(device_string);一根电话呢?
此代码是否试图逃避/使用隐藏的字符串初始化行为?是为了确保 stdDevString 内的 C 字符串无论如何都保持以 null 结尾?因为据我所知,将 std::string 初始化为非 null 终止的 C 字符串仍然会出现问题。
他们为什么不只打
std::string stdDevString = std::string(device_string);一根电话呢?
他们的所作所为没有充分的理由。给定std::string::string(const char*)构造函数,您可以简单地使用以下任意一个:
std::string stdDevString = device_string;
std::string stdDevString(device_string);
std::string stdDevString{device_string}; // C++11 { } syntax
Run Code Online (Sandbox Code Playgroud)
两步默认构造然后分配只是(糟糕的)程序员风格或疏忽。如果没有优化,它确实做了一些不必要的构建,但这仍然相当便宜。它可能已通过优化删除。不是什么大事 - 我怀疑我是否愿意在代码审查中提及它,除非它处于对性能极其敏感的区域,但绝对最好推迟声明变量,直到有一个有用的初始值可用于构造它们,并将其本地化一切都集中在一个地方:它不仅不易出错且可交叉引用,而且最大限度地减少了变量的范围,简化了其使用的推理。
是为了确保里面的C字符串
stdDevString无论如何都保持以null结尾?
不——这没有什么区别。由于 C++11,无论使用哪个构造函数,内部缓冲区都stdDevString将保持 NUL 终止,而 C++03 不一定终止 - 请参阅下面 C++03 详细信息的专用标题 - 但无论如何都不能保证如何完成构建/分配。
因为据我所知,将 an 初始化
std::string为非空终止的 C 字符串仍然会出现问题。
你是对的 - 你列出的任何构造选项都只会将 ASCIIZ 文本复制到std::string- 考虑到第一个 NUL ( '\0') 终止符。如果 char 数组不是以 NUL 结尾,则会出现问题。
(这是一个单独的问题,里面的缓冲区是否std::string保持 NUL 终止 - 上面讨论过)。
请注意,有一个单独的string(const char*, size_type)构造函数可以创建嵌入 NUL 的字符串,并且不会尝试比告知的内容进一步阅读(此处的构造函数 (4) )
无论以哪种方式std::string构造和初始化,在 C++11 之前,标准不要求它在字符串缓冲区内以 NUL 结尾。 std::string最好的想象是包含一堆潜在的不可打印(宽松地说,在 ftp/文件 I/O 意义上的二进制)字符,从地址开始data()并扩展size()字符。所以,如果你有:
std::string x("help");
x[4]; // undefined behaviour: only [0]..[3] are safe
x.at(4); // will throw rather than return '\0'
x.data()[4]; // undefined behaviour, equivalent to x[4] above
x.c_str()[4]; // safely returns '\0', (perhaps because a NUL was always
// at x[4], one was just added, or a new NUL-terminated
// buffer was just prepared - in which case data() may
// or may not start returning it too)
Run Code Online (Sandbox Code Playgroud)
请注意,std::string API 要求c_str()返回一个指向 NUL 终止值的指针。为此,它可以:
NUL始终主动在字符串缓冲区的末尾保留一个额外的内容(在这种情况下,该实现data[5] 恰好是安全的,但如果实现发生更改或代码被移植到另一个标准库实现等,代码可能会中断)反应性地等待直到c_str()被调用,然后:
data())有足够的容量,则追加 a并返回与返回NUL相同的指针值data()NUL它,并返回指向它的指针(通常但可选地,该缓冲区将替换将被删除的旧缓冲区,以便data()之后立即调用将返回返回的相同指针经过c_str())| 归档时间: |
|
| 查看次数: |
4067 次 |
| 最近记录: |