【问题标题】:Why is copy assignment called in this case?为什么在这种情况下调用复制分配?
【发布时间】:2016-06-04 16:59:41
【问题描述】:
template <typename InfoType>
class ObjPool {
public:
struct tag;
using size_type = unsigned;
using uid_type = IntWrapper<tag, size_type>;

uid_type add(InfoType&& newInfo) {
    if (removedUids_.size()) {
        uid_type reuse = removedUids_.back();
        removedUids_.pop_back();
        infos_[reuse] = newInfo;  // This line
        alive_[reuse] = true;
        ++size_;
        return reuse;
    }
    else {
        infos_.push_back(newInfo);
        alive_.push_back(true);
        ++size_;
        return uid_type(size_-1);
    }
}

// Other code
};

编译器产生错误:

无法分配“Graph::NodeInfo”类型的对象,因为它的复制赋值运算符被隐式删除 infos_[reuse] = newInfo;

我不太明白为什么?我定义了一个移动分配,并希望这一行调用移动版本而不是复制版本。

为什么

infos_[reuse] = std::move(newInfo);

这里有必要吗?

用c++11用clang编译。

【问题讨论】:

  • 如果有名字,就是左值。

标签: c++ c++11 clang


【解决方案1】:

右值引用类型的命名变量是左值(感谢@M.M 的更正)。它有一个名字,你可以获取它的地址,它与左值引用几乎相同。由于右值引用只能绑定到右值,因此移动赋值运算符不能采用(命名的)右值引用。调用 std::move 将使其成为右值(特别是 xvalue),以便将其传递给移动运算符。

来自cppreference

即使变量的类型是右值引用,由其名称组成的表达式也是左值表达式;

【讨论】:

  • 谢谢。那么这里newInfo被视为左值,那么newInfo的数据成员呢?例如,如果 v 是 InfoType 的成员,那么 newInfo.v 是被视为右值还是左值?
  • 您的意思是“使用右值引用类型声明的变量的名称是左值”。其他右值引用(例如 std::move) 返回的不是左值
  • 我很困惑,因为大多数带有移动构造函数/赋值的例子都没有在成员上应用 std::move。
  • @user69818 左值的成员也是左值(我不知道它不会是的实例),右值的成员是 xvalue。 Here 是一个简单的例子来展示它。如果没有std::movestatic_cast,它将无法编译。
  • @JamesRoot 我很困惑。那么为什么移动构造函数根本不应用 std::move 呢? C++ 入门和 Stroustrups 书中的移动构造函数示例在移动对象上没有 std::move。
猜你喜欢
  • 1970-01-01
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
  • 2017-06-11
相关资源
最近更新 更多