在本例中,为什么需要使用template_back移动
Why is move necessary with emplace_back in this example?
当使用选项1或选项2下的代码时,以下最小工作示例会编译,但当使用选项3下的代码后,不会编译。我假设emplace_back()
隐式使用/调用move
构造函数,那么为什么需要显式move()
呢?是否与r-value
与l-value
有关?或者这与std::unique_ptr
需要转移所有权有关?(我对这些概念还是个新手,尤其是在这种情况下。)
为完整起见,除非调用move()
,否则带有push_back()
的选项4也不会编译。
#include <iostream>
#include <vector>
#include <memory>
class Beta {
public:
Beta(int x, int y, int z): mX(x), mY(y), mZ(z) { };
int mX; int mY; int mZ;
};
class Alpha {
public:
std::vector<std::unique_ptr<Beta>> betaVec;
void addBeta(int x, int y, int z) {
// only choose one of the following options:
// option 1 (compiles)
std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
betaVec.emplace_back(move(pBeta));
// option 2 (compiles)
betaVec.emplace_back(std::make_unique<Beta>(x, y, z));
// option 3 (does not compile)
std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
betaVec.emplace_back(pBeta);
// option 4 (does not compile)
std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
betaVec.push_back(pBeta);
// option 5 (compiles)
std::unique_ptr<Beta> pBeta = std::make_unique<Beta>(x, y, z);
betaVec.push_back(move(pBeta));
}
};
int main() {
return 0;
}
注意:我不认为这是关于将unique_ptr
参数传递给函数的问题的重复,尽管链接问题的答案是有用的,因为这是关于在函数中定义unique_ptr
,然后将其移动到成员vector
,这样它就不会在函数结束时被破坏,此外,在这种情况下特别询问CCD_ 12。
此外,我认为在这种背景下给出解释是有用的,因为有时很难将解释从一个背景翻译到另一个背景。非常感谢。
我假设
emplace_back()
隐式使用/调用移动构造函数
对不起,你的假设是错误的。emplace_back
在适当的向量中构造对象,即它不是从其参数中复制/移动对象,而是直接构造元素,从而避免了复制/移动构造函数。
现在,如果你用同一个(但另一个)对象构造对象,那么当然会使用复制或移动构造函数,这就是你的情况。
那么为什么显式
move()
是必要的
因为您无法复制std::unique_ptr
。基本上,emplace_back
会做类似的事情:
new (place) T(std::forward<Ts>(args)...);
这就像你做了:T a(std::forward<Ts>(args)...)
(仅用于构建,它实际上并没有做同样的事情)。
现在可能更明显了:
T option1(std::move(pBeta)); // ok, move
T option3(pBeta); // error, copy
这与
r-value
与l-value
有关吗?或者这与std::unique_ptr
需要转让所有权有关?
嗯,在某种程度上,是的。std::unique_ptr
需要明确的所有权转移,这就是为什么复制被禁用而移动没有被禁用的原因(你仍然想转移所有权!复制可以在任何地方发生-为什么std::auto_ptr
被弃用,然后被删除)。默认情况下,右值使用移动语义,而左值则不使用。通过使用std::move
,你正在进行从左值到prvalue的转换,有效地"隐藏"了你有一个左值的事实,编译器会很高兴地离开它
- 表示"accepting anything for this template argument" C++概念的通配符
- 将对象移动到std::shared_ptr
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 将shared_ptr移动到<StructA>shared_ptr<变体<结构A、结构 B>>
- C / C++ 移位/偏移/向左或向右移动位图?
- MSVC将仅移动结构参数解释为指针
- 自定义先决条件对移动分配运算符有效吗
- 返回值优化:显式移动还是隐式
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 为什么复制而不是移动数据元素?
- 传递给std::function template的template参数究竟代表什么
- 可以使用移动语义更改或改进此C++代码吗?
- 使lambda不可复制/不可移动
- 在template中使用std::variant的template函数
- c++在使用指针时移动语义
- 将QGraphicsItem的移动区域限制在多边形区域内
- SendInput()鼠标移动计算
- 按值 C++ 返回时进行双倍移动
- 私有构造函数禁止使用template[_back]()来避免移动