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

nwwlzxa7  于 2023-01-28  发布在  其他
关注(0)|答案(4)|浏览(147)

SO文档中的字符串主题在备注部分中曾经说过:
从C++14开始,建议使用"foo"s而不是"foo",因为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 literals而不是const char[]文本有什么好处吗?

23c0lvtd

23c0lvtd1#

如果你是“几乎总是自动”人群中的一员,那么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代码被传递了一个指向字符串的指针和一个大小,这样,它就可以调用std::string构造函数,这个构造函数接受const char* * 和size_t *,所以不需要计算字符串的长度。
这里的建议并不是让你把每次使用的字面量都转换成s版本,如果你不介意char数组的限制,就使用它,建议是,如果你要把字面量存储在std::string中,最好在它还是字面量而不是模糊的const char*时完成。

kpbwa7wx

kpbwa7wx2#

使用"blah"s的建议与效率无关,而与新手代码的正确性有关。
没有C语言背景的C初学者,倾向于假设"blah"会导致一个合理的字符串类型的对象。例如,这样就可以写"blah" + 42这样的东西,它可以在许多脚本语言中工作。然而,在C中使用"blah" + 42,只会导致未定义的行为,寻址字符数组的末尾。
但是如果字符串文字被写成"blah"s,那么就会得到一个编译错误,这是更可取的。

0s0u357o

0s0u357o3#

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

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

r8xiu3jd4#

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

相关问题