复制初始化对 C++11 中的 move 有效吗?

Copy initialization is effective with move in C++11?

复制初始化是在内存中创建Hello,然后使用复制构造函数初始化s,对吧?

std::string s = std::string("Hello")

在引入移动语义的 C++11 之后,我可以说上面的代码与这种情况一样有效(消除复制):

std::string s("Hello");

编辑:请不要回答 stringstring 只是 class 的例子。 SSO 是不是这样我问的是什么。我问的一般。

当您使用小于 20 个字符的字符串(取决于实现)时,短字符串优化就会启动,无论如何都会复制所有内容。

但是为了回答您的问题,您的任何示例中都没有使用移动语义。在第一种情况下,即使复制构造函数和 string(const char*) 构造函数都必须可用,复制省略也会消除复制。

编辑:

为了解决您的编辑问题,如果您有一个初始化和一个初始化 + 移动构造函数,那么前者显然总是更快。我提出 SSO 的原因是因为人们认为移动操作总是很便宜(甚至免费),但不一定,有时甚至根本不会发生。

实际上,C++11 之前就是这种情况,因为 copy elision

请注意,std::string 移动起来不一定便宜,因为小字符串可能保存在对象本身中,而不是动态分配。这被称为 small string optimisation

简短回答:如果执行复制省略,性能应该相同。否则后者应该会更快。


长答案:

这个代码

std::string s = std::string("Hello")

应该在 C++11+ 代码中调用一个移动构造函数(它需要一个可访问的)。无论如何,在这种情况下 copy elision 是允许的,尽管没有强制要求(参见 [class.copy]/p31

When certain criteria are met, an implementation is allowed to omit the copy/move construction

这些概念在 C++11 之前的版本中已经存在(它们也适用于复制构造函数)。

关于表演问题:

The standard also describes a few situations where copying can be eliminated even if this would alter the program's behavior, the most common being the return value optimization. Another widely implemented optimization, described in the C++ standard, is when a temporary object of class type is copied to an object of the same type.[1] As a result, copy-initialization is usually equivalent to direct-initialization in terms of performance, but not in semantics; copy-initialization still requires an accessible copy constructor.[2]

Source - Copy elision

如果复制省略没有发生(例如,它已通过 -fno-elide-constructors 在 gcc 中被禁用,或者出于任何原因编译器不会执行它)那么性能可能 不会 是相同的,直接初始化应该更快(在这种情况下,std::string SSO 也可能对移动造成影响)