为什么没有std :: string构造函数来引用数组?

时间:2012-11-27 23:46:34

标签: c++

字符串文字是数组对象:

typeid("hello").name()   // char [6]

这看起来很方便,因为字符串文字(=数组)的大小在编译时是已知的。那么为什么std::string没有构造函数引用数组?

// this would be great
template <int N>
std::string(const char (& array)[N]);

相反,有些构造函数需要const char * sconst char * s, size_t n或两个InputIterator s(例如const char * begin, const char * end)。所有这些都有缺点;数组被隐式转换为指针并且大小信息丢失,因此使用各种方法将其取回。工作,但越来越疯狂的例子:

// std::string(const char * s) version:
std::string s1("hello");                      // calls std::strlen(s) internally

// std::string(const char * s, size_t n) version:
std::string s2("hello", 5);                   // programmer does std::strlen(s) mentally
std::string s3("hello", sizeof("hello"));     // have to repeat string literal

// macro helper to avoid repeating string literal (ugly and dangerous)
#define STRLIT(x) std::string(x, sizeof(x));  // could be a function I guess
std::string s4 = STRLIT("hello");             // not much improvement (and macros are evil)

// std::string(InputIterator begin, InputIterator end) version:
char tmp[] = "hello";                         // copy array
std::string s5(&tmp[0], &tmp[sizeof(tmp)]);   // so you can reference it twice

// or trust the compiler to return the same address for both literals
std::string s6(&"hello"[0], &"hello"[sizeof("hello")]);   // totally crazy

3 个答案:

答案 0 :(得分:2)

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

臃肿是可以避免的,但让我们将这个想法与来自永远引用的Raymond Chen的答案结合起来:

  

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

答案 1 :(得分:1)

在考虑构造函数是否应该使用char const (&)[N](对于某些静态确定的N)时,关键问题是结果std::string的内容应该是什么。对某些人来说可能是显而易见的,但我认为不是。考虑一下这个std::string("abc\0def")

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

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

    你得到第三个选择。看来,这是唯一理智的选择......

答案 2 :(得分:0)

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

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

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