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

Are basic_string literals faster or handled better at compile-time?

本文关键字:处理 更好 是否 string 文本 编译 basic      更新时间:2023-10-16

在浏览C++14/C++1y(n3690)草案时,我注意到在§21.7:中引入了basic_string litertal后缀

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文字是否有可能在运行时更快
  • 我的"天真"实施完全错误吗
  • ROM中的数据布局是否与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或类似的东西更好吗?

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

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

  • 我的"天真"实施完全错误吗

不,这是正确的。

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

可能不会,因为相关的basic_string构造函数不是constexpr,因此不符合静态初始化的条件,因此可能无法放入ROM,必须在运行时完成。

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

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

string fromLit = "A fabulous string"s;
string fromBare = string("A fabulous string");

看到fromBare中缺少什么了吗?让我为你解释一下:

string fromBare = string("A fabulous string"/*, NOTHING*/);

是的,如果没有…,你就无法获得字符串的长度。。。得到它的长度。这意味着fromBare必须遍历文字才能找到字符。在运行时。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;),第二个仍然更短。然而,到底发生了什么是清楚的。

它提供了更多的编译时安全性。

考虑如何构造一个嵌入null的std::字符串?

从包含null字符的字符串文字构造std::string的唯一方法是指定字符串文字的大小(容易出错)、使用initializer_list语法(详细)或通过多次调用push_back来执行某种循环(甚至更详细)。但是,使用literal构造函数,大小会自动为您传递,从而消除可能的错误源。