在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!" );
如这个答案所解释的那样,数组会退化为指针,但它们的维度会被去除。对于字符串字面量来说,这意味着它们在编译时已知的长度会丢失,必须通过迭代指向内存,直到找到一个零字节来重新计算它们的长度在运行时。 这不是最优的。
然而,使用模板参数推导将字符串字面量和一般的数组作为引用传递,可以保留它们的大小。
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);
的实例。 - chrisstd::string
太长了吗?如果是这样,可以使用std::string s(arr, 20);
来缓解。 - djspstd::string
的实现者和使用者都假设字符串中的所有字符都是非空的,并且字符串后的第一个字符为空。但如果一些开发人员粗心大意,这种假设就是错误的。我猜可以很容易地解决这个问题,即确定当\0
的放置假设被打破时,行为是未定义的。 - Aaron McDaidstring_view
。 - Kerrek SB