C++ 为什么对数组的引用没有std::string构造函数?

C++ 为什么对数组的引用没有std::string构造函数?,c++,C++,字符串文字是数组对象: typeid(“hello”).name()//字符[6] 这似乎很方便,因为字符串文本(=数组)的大小在编译时是已知的。那么为什么没有引用数组的std::string构造函数呢 //这太好了 模板 std::string(常量字符和数组)[N]); 相反,有些构造函数采用const char*s、const char*s、size\t n或两个inputierators(例如const char*begin、const char*end)。所有这些都有缺点;数组隐式

字符串文字是数组对象:

typeid(“hello”).name()//字符[6]
这似乎很方便,因为字符串文本(=数组)的大小在编译时是已知的。那么为什么没有引用数组的
std::string
构造函数呢

//这太好了
模板
std::string(常量字符和数组)[N]);
相反,有些构造函数采用
const char*s
const char*s、size\t n
或两个
inputierator
s(例如
const char*begin、const char*end
)。所有这些都有缺点;数组隐式转换为指针,大小信息丢失,因此使用各种方法将其取回。工作,但越来越疯狂的例子:

//std::string(const char*s)版本:
std::string s1(“hello”);//在内部调用std::strlen
//标准::字符串(常量字符*s,大小\u t n)版本:
std::string s2(“hello”,5);//程序员在精神上做std::strlen
std::string s3(“hello”,sizeof(“hello”);//必须重复字符串文字
//避免重复字符串文字的宏帮助器(丑陋且危险)
#定义STRLIT(x)std::string(x,sizeof(x));//我想可能是一个函数
std::string s4=STRLIT(“hello”);//没有多少改进(宏是邪恶的)
//标准::字符串(输入计算器开始,输入计算器结束)版本:
char tmp[]=“你好”//复制数组
std::字符串s5(&tmp[0],&tmp[sizeof(tmp)]);//所以你可以引用它两次
//或者信任编译器为两个文本返回相同的地址
std::string s6(&“hello”[0],&“hello”[sizeof(“hello”)]);//完全疯了

这样的模板化构造函数将针对
N
的每个值分别实例化。这可能会导致不必要的代码膨胀

膨胀是可以避免的,但让我们将这一想法与不断引用的答案结合起来:

“为什么不存在此功能?”的答案通常是“默认情况下,功能不存在。必须有人来实现它们。”


对于
N
的每个值,将分别实例化这样一个模板化构造函数。这可能会导致不必要的代码膨胀

膨胀是可以避免的,但让我们将这一想法与不断引用的答案结合起来:

“为什么不存在此功能?”的答案通常是“默认情况下,功能不存在。必须有人来实现它们。”


因为有一个使用迭代器的通用构造函数:

std::string s7(std::begin(container), std::end(container));

注意:假设std::begin/std::end使用c++11,但您可以很容易地快速编写类似的内容。

因为有一个使用迭代器的通用构造函数:

std::string s7(std::begin(container), std::end(container));

注意:假设std::begin/std::end使用c++11,但是您可以很容易地快速编写类似的内容。

考虑是否应该有一个构造函数接受字符常量(&)[N](对于一些静态确定的
N
)时,关键问题是结果
std::string
的内容应该是什么。对某些人来说,这可能是显而易见的,但我不认为是这样。考虑这个<代码> STD::String(“ABC \0DEF”)< /代码>:

  • 它可以是一个包含8个元素的字符串,包括两个空字节
  • 它可以是一个包含7个元素的字符串,不包括第二个空字节
  • 它可以是一个包含3个元素的字符串,不包括从第一个空字节开始的所有内容
  • 如果你使用

    std::cout << "string='" << "abc\0def" << "'\n";
    

    std::cout在考虑是否应该有一个构造函数采用
    char const(&)[N]
    (对于一些静态确定的
    N
    )时,关键问题是结果
    std::string
    的内容应该是什么。对某些人来说,这可能是显而易见的,但我不认为是这样。考虑这个<代码> STD::String(“ABC \0DEF”)< /代码>:

  • 它可以是一个包含8个元素的字符串,包括两个空字节
  • 它可以是一个包含7个元素的字符串,不包括第二个空字节
  • 它可以是一个包含3个元素的字符串,不包括从第一个空字节开始的所有内容
  • 如果你使用

    std::cout << "string='" << "abc\0def" << "'\n";
    

    std::您是否可以编写自己的
    make_string
    函数来执行此操作。仅供参考,
    sizeof
    捕获空字节并返回6。
    STRLIT
    可以是内联函数,而不是宏
    tmeplate std::string strlit(const char(&str)[len]){return std::string(str,len);}
    (这也是Pubby建议的)字符串文本是数组对象,不是类型。一个好的编译器会为文本字符串提供一个固定时间版本的strlen。您可以编写自己的
    make_string
    函数来实现这一点。仅供参考,
    sizeof
    捕获空字节并返回6。
    STRLIT
    可以是一个内联函数,而不是宏
    tmeplate std::string strlit(const char(&str)[len]){return std::string(str,len);}
    (这也是Pubby所建议的)字符串文字是数组对象,而不是类型。一个好的编译器会为文字字符串提供一个固定时间版本的
    strlen
    。无意义,零构造所有成员,然后调用
    assign(ptr,size)
    ,内联后,每个
    N
    都不会膨胀,要扩展@Mooing Duck所说的内容,使用C++11,它所要做的就是委托给
    字符串(ptr,size)
    构造函数。代表团几乎肯定会加入进来。没有膨胀。好吧,我建议的是稍微不太可能内联,但碰巧也在C++03中工作,零构造所有成员,然后调用
    assign(ptr,size)
    ,内联后,每个
    N
    都没有膨胀,要扩展@Mooing Duck所说的内容,使用C++11,它所要做的就是委托给
    字符串(ptr,size)
    constructor。委托几乎肯定是内联的。没有膨胀。好吧,我建议的是内联的可能性稍微小一些