文字列リテラルは配列オブジェクトです。
typeid("hello").name() // char [6]
文字列リテラル(=配列)の大きさはコンパイル時に分かるので便利そうです。では、なぜstd::string
配列への参照を取るコンストラクターがないのでしょうか?
// this would be great
template <int N>
std::string(const char (& array)[N]);
代わりにconst char * s
、const char * s, size_t n
または 2 つ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