保证在 C++17 和 emplace_back(..) 中复制省略
Guaranteed copy elision in C++17 and emplace_back(...)
emplace_back(...( 是在 C++11 中引入的,以防止创建临时对象。现在有了 C++17 纯值,就更纯净了,这样它们就不会再导致临时的产生(有关更多信息,请参阅此问题(。现在我仍然不完全了解这些变化的后果,我们还需要emplace_back(...)
还是可以回去再次使用push_back(...)
?
push_back
和emplace_back
成员函数都会在预分配缓冲区的某个位置创建其value_type
T
的新对象。这是由向量的分配器完成的,默认情况下,它使用放置新机制进行此构造(放置新基本上只是在内存中指定位置构造对象的一种方法(。
然而:
emplace_back
将其参数完全转发给T
的构造函数,因此选择与这些参数最匹配的构造函数。push_back(T&&)
内部使用move 构造函数(如果存在且未引发(来初始化新元素。移动构造函数的这种调用不能省略,并且始终使用。
请考虑以下情况:
std::vector<std::string> v;
v.push_back(std::string("hello"));
std::string
的移动构造函数总是在这里调用,它跟在转换构造函数之后,转换构造函数从字符串文字创建一个字符串对象。在这种情况下:
v.emplace_back("hello");
没有调用移动构造函数,向量的元素由std::string
的转换构造函数直接初始化。
这并不一定意味着push_back
效率较低。编译器优化可能会消除所有其他指令,最终这两种情况可能会生成完全相同的汇编代码。只是不能保证。
顺便说一下,如果push_back
按值(void push_back(T param);
(传递参数,那么这将是应用复制省略的一个案例。即,在:
v.push_back(std::string("hello"));
参数param
将由临时构造函数构造。这种移动结构将是复制省略的候选者。然而,这种方法根本不会改变push_back
体内矢量元素的强制移动构造。
你可能会在这里看到:std::vector::p ush_back,这种方法需要CopyInsertable或MoveInsertable,它也需要const T& value
或T&& value
,所以我看不出elision在这里如何使用。
在以下示例中使用了强制复制 ellision 的新规则:
struct Data {
Data() {}
Data(const Data&) = delete;
Data(Data&&) = delete;
};
Data create() {
return Data{}; // error before c++17
}
void foo(Data) {}
int main()
{
Data pf = create();
foo(Data{}); // error before c++17
}
因此,您有一个不支持复制/移动操作的类。为什么,因为也许它太贵了。上面的例子是一种始终有效的工厂方法。使用新规则,您无需担心编译器是否实际使用 elision - 即使您的类支持复制/移动。
我不认为新规则会让push_back更快。 emplace_back仍然更有效,但不是因为复制,而是因为它创建对象并将参数转发到它。
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 使用strcpy将char数组的元素复制到另一个数组
- 是否可以初始化不可复制类型的成员变量(或基类)
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- C++ Windows 驱动程序MSB3030无法复制该文件,因为它找不到
- 复制列表初始化的隐式转换的等级是多少
- 当从函数参数中的临时值调用复制构造函数时
- 有可能在Armadillo中复制MATLAB circshift方法吗
- 复制几乎为空的数组的最快方法
- 以下示例中如何避免代码复制?C++/库达
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 文件系统:复制功能的速度秘诀是什么
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 使lambda不可复制/不可移动