将用户定义的文字用于字符串而不是字符串文字的优点

时间:2016-07-28 02:51:31

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

SO文档中的字符串主题用于说明,在备注部分:

  

从C ++ 14开始,不建议使用"foo",而是使用"foo"s,因为s是一个字符串文字,可以转换const char * {{ 1}}到"foo" std::string

我看到的唯一优势

"foo"

而不是

std::string str = "foo"s;

是第一种情况,编译器可以执行copy-elision(我认为),这比第二种情况下的构造函数调用要快。

尽管如此,这是(尚未)保证,所以第一个也可能会调用构造函数,复制构造函数。

忽略必需使用std::string str = "foo"; 文字的情况,例如

std::string

使用std::string str = "Hello "s + "World!"s; 文字而不是std::string文字是否有任何好处?

4 个答案:

答案 0 :(得分:47)

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

auto str = "Foo"s;

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

这对于自动退货类型扣除也很重要:

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

或任何形式的类型演绎,真的:

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

foo("Foo"s);
  

我看到使用[...]而不是[...]的唯一优势是,在第一种情况下,编译器可以执行copy-elision(我认为),这将比第二次构造函数调用更快情况下。

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

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

有问题的建议不适合您将每个使用文字转换为size_t版本。如果您对s数组的限制很好,请使用它。建议是,如果你要将这个文字存储在char中,那么最好还是将它完成,而它仍然是文字而不是模糊的std::string

答案 1 :(得分:19)

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

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

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

答案 2 :(得分:12)

此外,UDL使字符串

中的\0变得更容易
std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s

答案 3 :(得分:2)

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