【发布时间】:2014-10-31 06:57:51
【问题描述】:
在 C++ 中,字符串字面量的类型是 const char [N],其中 N,如 std::size_t,是字符数加一(零字节终止符)。它们驻留在静态存储中,从程序初始化到终止都可用。
通常,采用常量字符串的函数不需要std::basic_string 的接口,或者更愿意避免动态分配;例如,他们可能只需要字符串本身及其长度。 std::basic_string 特别是必须提供一种从语言的本机字符串文字构造的方法。此类函数提供了一个采用 C 风格字符串的变体:
void function_that_takes_a_constant_string ( const char * /*const*/ s );
// Array-to-pointer decay happens, and takes away the string's length
function_that_takes_a_constant_string( "Hello, World!" );
正如this answer 中所解释的,数组衰减为指针,但它们的维度被带走了。在字符串文字的情况下,这意味着它们的长度(在编译时已知)会丢失,并且必须在 运行时通过遍历指向的内存直到找到零字节来重新计算。这不是最优的。
但是,字符串字面量,通常是数组,可以使用模板参数推导作为引用传递以保持其大小:
template<std::size_t N>
void function_that_takes_a_constant_string ( const char (& s)[N] );
// Transparent, and the string's length is kept
function_that_takes_a_constant_string( "Hello, World!" );
模板函数可以作为另一个函数的代理,真正的函数,它将接受一个指向字符串及其长度的指针,从而避免代码暴露并保持长度。
// Calling the wrapped function directly would be cumbersome.
// This wrapper is transparent and preserves the string's length.
template<std::size_t N> inline auto
function_that_takes_a_constant_string
( const char (& s)[N] )
{
// `s` decays to a pointer
// `N-1` is the length of the string
return function_that_takes_a_constant_string_private_impl( s , N-1 );
}
// Isn't everyone happy now?
function_that_takes_a_constant_string( "Hello, World!" );
为什么不更广泛地使用它?特别是,为什么std::basic_string 没有带有建议签名的构造函数?
注意:我不知道建议的参数是如何命名的;如果您知道如何,请建议问题标题的版本。
【问题讨论】:
-
std::string将其作为参数将引入char arr[100]; fillFirst20Chars(arr); std::string s(arr);的实例。 -
@chris 很抱歉,但我不明白你的意思。您的意思是创建的
std::string会太长吗?如果是这样,可以使用std::string s(arr, 20);来缓解这种情况。 -
我想问题是
std:: string的实现者和用户假设字符串中的所有字符都是非空的,并且字符串后面的第一个字符是空的。但是,如果某些开发人员粗心,这种假设将是不正确的。我想这可以通过确定行为未定义来轻松解决,因为关于\0的位置的假设被打破了。 -
在 Library Fundamentals TS 中查找
string_view。 -
@Kalrish,是的,你可以,但是 a) 现有代码没有,并且 b) 它很可能是意外且未被检测到的。