62

SO文档中的字符串主题曾经在备注部分中说:

从 C++14 开始,"foo"建议使用 ,而不是使用 ,因为它是"foo"s字符串s文字,它将 转换const char * "foo"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[]吗?

4

4 回答 4

54

如果您是“几乎总是自动”人群中的一员,那么 UDL 就非常重要。它可以让你这样做:

auto str = "Foo"s;

因此,str将是一个真正的std::string,而不是一个const char*。因此,它允许您决定何时执行哪个操作。

这对于自动返回类型扣除也很重要:

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

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

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

foo("Foo"s);

我看到使用 [...] 而不是 [...] 的唯一优点是,在第一种情况下,编译器可以执行复制省略(我认为),这比第二种情况下的构造函数调用要快。

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

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 代码被传递了一个指向字符串的指针和一个大小。因此,它可以调用带有 aa的std::string构造函数。所以不需要计算字符串的长度。const char* size_t

有问题的建议不是让您四处走动并将文字的每次使用都转换为s版本。如果您对 s 数组的限制感到满意char,请使用它。建议是,如果您要将文字存储在 astd::string中,最好在它仍然是文字而不是模糊的时候完成const char*

于 2016-07-28T03:09:08.630 回答
22

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

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

但是,如果将该字符串文字写为"blah"sthen 则会出现编译错误,这是更可取的。

于 2016-07-28T03:22:25.660 回答
16

此外,UDL 更容易\0在字符串中包含

std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s
于 2016-07-28T08:31:00.637 回答
2
  1. 使用 C++ 字符串文字意味着我们不需要调用strlen来计算长度。编译器已经知道了。
  2. 可能允许库实现,其中字符串数据指向全局空间中的内存,将使用 C 文字必须始终强制数据的副本在构造时堆内存。
于 2016-07-28T03:13:19.480 回答