对字符串使用用户定义的文字而不是字符串文字的优点

Advantages of using user-defined literal for strings instead of string literal

SO Documentation中的strings主题曾经说过,在Remarks部分:

Since C++14, instead of using "foo", it is recommended to use "foo"s, as s is a string literal, which converts the const char * "foo" to std::string "foo".

我看到使用

的唯一优势
std::string str = "foo"s;

而不是

std::string str = "foo";

在第一种情况下,编译器可以执行复制省略(我认为),这将比第二种情况下的构造函数调用更快。

尽管如此,这(尚未)得到保证,因此第一个也可能调用构造函数,即复制构造函数。

忽略需要使用std::string文字的情况,例如

std::string str = "Hello "s + "World!"s;

使用 std::string 文字而不是 const char[] 文字有什么好处吗?

如果您是 "Almost Always Auto" 人群中的一员,那么 UDL 非常重要。它可以让你这样做:

auto str = "Foo"s;

因此,str 将是真正的 std::string,而不是 const char*。因此,它允许您决定何时做什么。

这对自动return类型推导也很重要:

[]() {return "Foo"s;}

或任何形式的类型推导,真的:

template<typename T>
void foo(T &&t) {...}

foo("Foo"s);

The only advantage I see using [...] instead of [...] is that in the first case the compiler can perform copy-elision (I think), which would be faster than the constructor call in the second case.

复制省略并不比构造函数调用快。无论哪种方式,您都在调用对象的构造函数之一。问题是哪一个:

std::string str = "foo";

这将引发对 std::string 的构造函数的调用,该构造函数采用 const char*。但是由于 std::string 必须将字符串复制到它自己的存储中,因此它必须获得字符串的长度才能这样做。由于它不知道长度,因此该构造函数被迫使用 strlen 来获取它(从技术上讲,char_traits<char>::length,但这可能不会更快)。

对比:

std::string str = "foo"s;

这将使用具有此原型的 UDL 模板:

string operator "" s(const char* str, size_t len);

看,编译器 知道字符串文字的长度。因此 UDL 代码被传递了一个指向字符串的指针和一个大小。因此,它可以调用带有 const char* std::string 构造函数和 size_t。所以不需要计算字符串的长度。

有问题的建议不是让您四处走动并将每个 文字使用转换为s 版本。如果您不介意 char 数组的限制,请使用它。建议是,如果您要将该文字存储在 std::string 中,最好在它仍然是文字而不是模糊的 const char*.

时完成它。
  1. 使用 C++ 字符串文字意味着我们不需要调用 strlen 来计算长度。编译器已经知道了。
  2. 可能允许库实现,其中字符串数据指向全局内存space将使用 C 文字,必须始终强制数据副本在构造时堆内存。

使用"blah"s的建议与效率无关,与新手代码的正确性有关。

没有 C 语言背景的 C++ 新手倾向于假设 "blah" 会产生某种合理字符串类型的对象。例如,这样就可以编写 "blah" + 42 之类的东西,它适用于许多脚本语言。然而,在 C++ 中使用 "blah" + 42,只会导致未定义的行为,寻址超出字符数组的末尾。

但是如果该字符串文字被写成 "blah"s 那么一个人反而会得到一个编译错误,这是更可取的。

此外,UDL 使得在字符串

中包含 [=11=] 更容易
std::string s = "foo[=10=]bar"s; // s contains a [=10=] in its middle.
std::string s2 = "foo[=10=]bar"; // equivalent to "foo"s