gpt4 book ai didi

c++ - 为什么在此示例中必须使用 emplace_back move ?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:59:42 24 4
gpt4 key购买 nike

以下最小工作示例在使用选项 1 或选项 2 下的代码时编译,但在使用选项 3 下的代码时编译。我假设 emplace_back() 隐式使用/调用 move 构造函数,那么为什么需要显式 move() 呢?它与 r-valuel-value 有关系吗?或者这是否与需要转让所有权的 std::unique_ptr 有关? (我对这些概念还是陌生的,尤其是在这种情况下。)

为了完整性,带有 push_back() 的选项 4 也不会编译,除非调用 move()

#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;
}

注意:我不认为这是 this question 的拷贝关于将 unique_ptr 参数传递给函数,即使链接问题的答案很有用,因为这是在询问关于定义 unique_ptr within 函数然后将它 move 到一个成员 vector 中,这样它就不会在函数结束时被销毁,而且,在这个上下文中专门询问 emplace_back()

此外,我认为在这种情况下给出解释会很有用,因为有时很难将解释从一种情况翻译到另一种情况。谢谢!

最佳答案

I was under the assumption that emplace_back() implicitly uses/calls a move constructor

抱歉,您的假设是错误的。 emplace_back在 vector 中就地构造对象,即不是从其参数复制/move 对象,而是直接构造元素,这避免了复制/move 构造函数。

现在,如果您使用相同(但另一个)对象构造对象,那么当然会使用复制构造函数或 move 构造函数,这就是您的情况。

so why is an explicit move() necessary

因为你不能复制 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

Does it have something to do with r-value vs. l-value? Or does this have to do with std::unique_ptr needing to transfer ownership?

嗯,在某种程度上,是的。 std::unique_ptr需要明确的所有权转移,这就是为什么复制被禁用而 move 没有被禁用的原因(你仍然想转移所有权!而且复制可以随处发生 - 为什么 std::auto_ptr 被弃用,然后被删除)。默认情况下,右值使用 move 语义,而左值则不使用。通过使用 std::move ,您正在进行从左值到纯右值的转换,有效地“隐藏”了您拥有左值的事实,并且编译器会很乐意从它转移。

关于c++ - 为什么在此示例中必须使用 emplace_back move ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47313833/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com