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

时间:2013-08-26 08:11:01

标签: c++ string literals c++14 user-defined-literals

在浏览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文字在运行时是否有可能更快?
  • 我的“幼稚”实施完全错了吗?
  • 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或编译时类似的东西会更好吗?

3 个答案:

答案 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进行某种循环(更详细)。但是,使用文字构造函数时,会自动为您传入大小,从而消除可能的错误来源。