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

时间:2022-05-28 22:28:31

The strings topic in the SO Documentation used to say, in the Remarks section:

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

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".

由于c++ 14,不使用“foo”,建议使用“foo”s,因为s是字符串文字,它将const char * foo”转换为std::string“foo”。

The only advantage I see using

我看到的唯一优点是使用

std::string str = "foo"s;

instead of

而不是

std::string str = "foo";

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.

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

Nonetheless, this is (not yet) guaranteed, so the first one might also call a constructor, the copy constructor.

尽管如此,这是(还没有)保证的,所以第一个可能会调用构造函数,即copy构造函数。

Ignoring cases where it is required to use std::string literals like

忽略需要使用std::string literals如的情况

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

is there any benefit of using std::string literals instead of const char[] literals?

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

4 个解决方案

#1


44  

If you're part of the "Almost Always Auto" crowd, then the UDL is very important. It lets you do this:

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

auto str = "Foo"s;

And thus, str will be a genuine std::string, not a const char*. It therefore permits you to decide when to do which.

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

This is also important for auto return type deduction:

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

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

Or any form of type deduction, really:

或者任何形式的演绎,真的:

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.

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

Copy-elision is not faster than the constructor call. Either way, you're calling one of the object's constructors. The question is which one:

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

std::string str = "foo";

This will provoke a call to the constructor of std::string which takes a const char*. But since std::string has to copy the string into its own storage, it must get the length of the string to do so. And since it doesn't know the length, this constructor is forced to use strlen to get it (technically, char_traits<char>::length, but that's probably not going to be much faster).

这将引发对std::string构造函数的调用,该构造函数使用const char*。但是由于std::string必须将字符串复制到它自己的存储中,所以它必须获得字符串的长度。由于它不知道长度,所以这个构造函数不得不使用strlen来获取它(严格地说,char_traits : length,但是可能不会快很多)。

By contrast:

相比之下:

std::string str = "foo"s;

This will use the UDL template that has this prototype:

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

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

See, the compiler knows the length of a string literal. So the UDL code is passed a pointer to the string and a size. And thus, it can call the std::string constructor that takes a const char* and a size_t. So there's no need for computing the string's length.

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

The advice in question is not for you to go around and convert every use of a literal into the s version. If you're fine with the limitations of an array of chars, use it. The advice is that, if you're going to store that literal in a std::string, it's best to get that done while it's still a literal and not a nebulous const char*.

问题的建议不是让你到处去,把一个文字的每一个用法转换成s版本。如果您对chars数组的限制没有问题,请使用它。建议是,如果要将该文字存储在std::string中,最好在它仍然是一个文字而不是一个模糊的const char*时完成它。

#2


17  

The advice to use "blah"s has nothing to do with efficiency and all to do with correctness for novice code.

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

C++ novices who don't have a background in C, tend to assume that "blah" results in an object of some reasonable string type. For example, so that one can write things like "blah" + 42, which works in many script languages. With "blah" + 42 in C++, however, one just incurs Undefined Behavior, addressing beyond the end of the character array.

没有C语言背景的c++新手,倾向于认为“blah”会导致某种合理的字符串类型。例如,一个人可以写“blah”+ 42,这在很多脚本语言中都是有效的。然而,在c++中使用“blah”+ 42,只会导致未定义的行为,在字符数组的末尾寻址。

But if that string literal is written as "blah"s then one instead gets a compilation error, which is much preferable.

但是,如果字符串文字被写成“blah”,那么就会出现编译错误,这是更可取的。

#3


10  

In addition, UDL makes it easier to have \0 in the string

此外,UDL使字符串中有\0变得更容易

std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s

#4


2  

  1. Using a C++ string literal means we do not need to call strlen to compute the length. The compiler already knows it.
  2. 使用c++字符串字面量意味着我们不需要调用strlen来计算长度。编译器已经知道了。
  3. Might allow library implemetations where the string data points to memory in global space will using C literals must always force a copy of the data to heap memory on construction.
  4. 可能允许库实现,其中字符串数据指向全局空间中的内存,使用C文字必须始终强制数据的副本在构造时堆内存。

#1


44  

If you're part of the "Almost Always Auto" crowd, then the UDL is very important. It lets you do this:

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

auto str = "Foo"s;

And thus, str will be a genuine std::string, not a const char*. It therefore permits you to decide when to do which.

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

This is also important for auto return type deduction:

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

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

Or any form of type deduction, really:

或者任何形式的演绎,真的:

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.

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

Copy-elision is not faster than the constructor call. Either way, you're calling one of the object's constructors. The question is which one:

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

std::string str = "foo";

This will provoke a call to the constructor of std::string which takes a const char*. But since std::string has to copy the string into its own storage, it must get the length of the string to do so. And since it doesn't know the length, this constructor is forced to use strlen to get it (technically, char_traits<char>::length, but that's probably not going to be much faster).

这将引发对std::string构造函数的调用,该构造函数使用const char*。但是由于std::string必须将字符串复制到它自己的存储中,所以它必须获得字符串的长度。由于它不知道长度,所以这个构造函数不得不使用strlen来获取它(严格地说,char_traits : length,但是可能不会快很多)。

By contrast:

相比之下:

std::string str = "foo"s;

This will use the UDL template that has this prototype:

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

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

See, the compiler knows the length of a string literal. So the UDL code is passed a pointer to the string and a size. And thus, it can call the std::string constructor that takes a const char* and a size_t. So there's no need for computing the string's length.

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

The advice in question is not for you to go around and convert every use of a literal into the s version. If you're fine with the limitations of an array of chars, use it. The advice is that, if you're going to store that literal in a std::string, it's best to get that done while it's still a literal and not a nebulous const char*.

问题的建议不是让你到处去,把一个文字的每一个用法转换成s版本。如果您对chars数组的限制没有问题,请使用它。建议是,如果要将该文字存储在std::string中,最好在它仍然是一个文字而不是一个模糊的const char*时完成它。

#2


17  

The advice to use "blah"s has nothing to do with efficiency and all to do with correctness for novice code.

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

C++ novices who don't have a background in C, tend to assume that "blah" results in an object of some reasonable string type. For example, so that one can write things like "blah" + 42, which works in many script languages. With "blah" + 42 in C++, however, one just incurs Undefined Behavior, addressing beyond the end of the character array.

没有C语言背景的c++新手,倾向于认为“blah”会导致某种合理的字符串类型。例如,一个人可以写“blah”+ 42,这在很多脚本语言中都是有效的。然而,在c++中使用“blah”+ 42,只会导致未定义的行为,在字符数组的末尾寻址。

But if that string literal is written as "blah"s then one instead gets a compilation error, which is much preferable.

但是,如果字符串文字被写成“blah”,那么就会出现编译错误,这是更可取的。

#3


10  

In addition, UDL makes it easier to have \0 in the string

此外,UDL使字符串中有\0变得更容易

std::string s = "foo\0bar"s; // s contains a \0 in its middle.
std::string s2 = "foo\0bar"; // equivalent to "foo"s

#4


2  

  1. Using a C++ string literal means we do not need to call strlen to compute the length. The compiler already knows it.
  2. 使用c++字符串字面量意味着我们不需要调用strlen来计算长度。编译器已经知道了。
  3. Might allow library implemetations where the string data points to memory in global space will using C literals must always force a copy of the data to heap memory on construction.
  4. 可能允许库实现,其中字符串数据指向全局空间中的内存,使用C文字必须始终强制数据的副本在构造时堆内存。