【问题标题】:Are basic_string literals faster or handled better at compile-time?basic_string 文字在编译时是否更快或处理得更好?
【发布时间】:2013-08-28 16:06:46
【问题描述】:

在浏览 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 是否更好,或者在编译时类似的东西?

【问题讨论】:

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


    【解决方案1】:
    • 是否有可能使用 basic_string 文字在运行时更快?

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

    • 我的“幼稚”实现完全错误吗?

    不,它是正确的。

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

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

    【讨论】:

      【解决方案2】:

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

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

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

      看到fromBare 中缺少什么了吗?让我为你拼写出来:

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

      是的,你不能得到字符串的 length 没有...得到它的长度。这意味着 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;),第二个仍然更短。但很清楚到底发生了什么。

      【讨论】:

      • 非常好!确实有长度是一个优势。
      • 关于性能,我怀疑字符串文字是否会促进使用静态常量:static std::string lit( "Literal" );;它们甚至可能明显变慢。然而,必须发明一个名称并声明一个额外的变量是一件痛苦的事情,而字符串文字无疑是基于这些理由的改进。
      【解决方案3】:

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

      考虑How do you construct a std::string with an embedded null?

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

      【讨论】:

      • 有趣的一点,但很少见。包含\0 的字符串文字会发生,但很少发生。由于作者可以控制字符串文字,因此他只介绍了一个小问题。尽管如此,+1,对于有趣的方面。
      猜你喜欢
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-07
      • 2010-11-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多