String literals are array objects:
typeid("hello").name() // char [6]
This seems convenient because the size of the string literal (=array) is known at compile time. So why is there no constructor to std::string
that takes a reference to an array?
// this would be great
template <int N>
std::string(const char (& array)[N]);
Instead there are constructors that take const char * s
, const char * s, size_t n
or two InputIterator
s (eg. const char * begin, const char * end
). All of these have drawbacks; the array is implicitly converted to a pointer and the size information is lost, so various methods are used to get it back. Working, but increasingly crazy examples:
// 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
Such a templated constructor would be separately instantiated for each value of N
. This could result in unnecessary code bloat.
The bloat is avoidable, but let's combine this thought with an answer from the ever-quotable Raymond Chen :
The answer to "Why doesn't this feature exist?" is usually "By default features don't exist. Somebody has to implement them."
The key question when considering whether there should be a constructor taking a char const (&)[N]
(for some statically determined N
) is what the content of the resulting std::string
should be. It might be obvious to some what it should be but I don't think it is. Consider this std::string("abc\\0def")
:
If you use
std::cout << "string='" << "abc\0def" << "'\n";
you get the third option. It seems, this is the only sane alternative...
Because there is a generic constructor that uses iterators:
std::string s7(std::begin(container), std::end(container));
Note: assumes c++11 for std::begin/std::end but you can quickly write something similar really easyily.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.