basic_string文字是否更快或在编译时处理得更好?

tow*_*owi 8 c++ string literals user-defined-literals c++14

略过C++ 14/C++ 1y(n3690)的草案,我注意到在第21.7节中引入了basic_stringlitertal后缀:

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);
}
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:

  • basic_string文字在运行时是否有可能更快?
  • 我的"幼稚"实施完全错了吗?
  • ROM中的数据布局是否可以与basic_string文字不同,或者在编译时与运行时的任何其他差异?

背景

我知道这允许直接使用这样的字符串文字:

std::string s1 = "A fabulous string"s;

void sfunc(std::string arg);

int main() {
    sfunc("argument"s);
}
Run Code Online (Sandbox Code Playgroud)

但是,依赖转换构造函数 的优点是什么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
}
Run Code Online (Sandbox Code Playgroud)

据我所知,实现operator "" s()基本上会是这样的:

std::string operator "" s(const char* lit, size_t sz) {
    return std::string(lit, sz);
}
Run Code Online (Sandbox Code Playgroud)

所以,只需使用相同的c'tor.我的猜测是,这必须在运行时完成,我错了吗?

编辑:正如尼科尔博拉斯正确地指出我的例子下面没有使用相同的构造函数,但是具有额外长度的构造函数 - 显然对于构造非常有用.这给我留下了一个问题:编译器将字符串文字放入ROM或编译时类似的东西会更好吗?

Jon*_*ely 6

  • 使用basic_string文字在运行时是否有可能更快?

如前所述,字符串长度是已知的并自动传递给构造函数.

  • 我的"幼稚"实施完全错了吗?

不,这是对的.

  • ROM中的数据布局是否可以与basic_string文字不同,或者在编译时与运行时的任何其他差异?

可能不是,因为相关的basic_string构造函数不是constexpr那样就没有资格进行静态初始化,所以可能无法放入ROM并且必须在运行时完成.


Nic*_*las 5

所以,只是使用相同的c'tor。

好的,让我们看看它会是什么样子:

string fromLit = "A fabulous string"s;
string fromBare = string("A fabulous string");
Run Code Online (Sandbox Code Playgroud)

看到有什么遗漏了fromBare吗?小编为你一一解读:

string fromBare = string("A fabulous string"/*, NOTHING*/);
Run Code Online (Sandbox Code Playgroud)

是的,你不能得到字符串的长度,除非......得到它的长度。这意味着fromBare必须遍历文字才能找到\0字符。在运行时。fromLit将不会; 编译器提供字符串的长度作为编译时确定的参数。任何值得使用的编译器都会将长度烘焙到可执行代码中。

即使情况并非如此,由于其他原因,它仍然更好。考虑一下:

void SomeFunc(const std::string &);
void SomeFunc(const char *);

SomeFunc("Literal");
SomeFunc("Literal"s);
SomeFunc(std::string("Literal"));
Run Code Online (Sandbox Code Playgroud)

最后两个做同样的事情(减去我之前提出的观点),但其中一个短得多。即使你雇用using std::string(或愚蠢地using namespace std;),第二个仍然更短。然而,究竟发生了什么事情却很清楚。