在浏览C ++ 14 / C ++ 1y(n3690)的草案时,我注意到在第21.7节中引入了 basic_string
文字后缀:
inline namespace literals {
inline namespace string_literals {
// 21.7, suffix for basic_string literals:
string operator "" s(const char *str, size_t len);
u16string operator "" s(const char16_t *str, size_t len);
u32string operator "" s(const char32_t *str, size_t len);
wstring operator "" s(const wchar_t *str, size_t len);
}
}
我的问题是:
basic_string
文字在运行时是否有可能更快?basic_string
文字不同,还是在编译时与运行时的任何其他差异?我知道这允许直接使用这样的字符串文字:
std::string s1 = "A fabulous string"s;
void sfunc(std::string arg);
int main() {
sfunc("argument"s);
}
但与依赖转换构造函数 string(const char*)
相比,有什么优势?
“旧”代码看起来:
std::string s1 = "A fabulous string"; // c'tor string(const char*)
void sfunc(std::string arg);
int main() {
sfunc("argument"); // auto-conversion via same c'tor
}
据我所知,operator "" s()
的实现基本上是这样的:
std::string operator "" s(const char* lit, size_t sz) {
return std::string(lit, sz);
}
所以,只需使用相同的c'tor。我的猜测是,这必须在运行时完成,我错了吗?
编辑:正如 Nicol Bolas 在我的示例下正确指出不使用相同的构造函数,但是具有额外长度的构造函数 - - 显然,这对施工非常有用。这给我留下了一个问题:编译器将字符串文字放入ROM或编译时类似的东西会更好吗?
答案 0 :(得分:6)
- 使用basic_string文字在运行时是否有可能更快?
如前所述,字符串长度已知并自动传递给构造函数。
- 我的“幼稚”实施完全错了吗?
不,这是对的。
- ROM中的数据布局可以与basic_string文字不同,还是在编译时与运行时的任何其他差异?
可能不是,因为相关的basic_string
构造函数不是constexpr
所以没有资格进行静态初始化,因此可能无法放入ROM并且必须在运行时完成
答案 1 :(得分:4)
所以,只需使用相同的c'tor。
好的,让我们看看它会是什么样子:
string fromLit = "A fabulous string"s;
string fromBare = string("A fabulous string");
查看fromBare
中缺少的内容?让我为你拼出来:
string fromBare = string("A fabulous string"/*, NOTHING*/);
是的,你不能得到字符串的长度而没有...得到它的长度。这意味着fromBare
必须遍历文字才能找到\0
字符。在运行时。 fromLit
不会;编译器提供字符串的长度作为编译时确定的参数。任何值得使用的编译器都会将长度加到可执行代码中。
即使不是的情况,由于其他原因,它仍然更好。考虑一下:
void SomeFunc(const std::string &);
void SomeFunc(const char *);
SomeFunc("Literal");
SomeFunc("Literal"s);
SomeFunc(std::string("Literal"));
最后两个做同样的事情(减去我之前提出的观点),但其中一个是很多更短。即使您使用using std::string
(或愚蠢地using namespace std;
),第二个仍然更短。然而,很清楚究竟发生了什么。
答案 2 :(得分:1)
它提供了更多的编译时安全性。
考虑How do you construct a std::string with an embedded null?
从包含空字符的字符串文字构造std::string
的唯一方法是指定字符串文字的大小(容易出错),使用initializer_list
语法(详细)或者通过多次调用push_back
进行某种循环(更详细)。但是,使用文字构造函数时,会自动为您传入大小,从而消除可能的错误来源。