提问人:stevenhz 提问时间:10/17/2022 更新时间:10/17/2022 访问量:454
C2280 尝试引用已删除函数时出错 [duplicate]
C2280 error attempint to reference a deleted function [duplicate]
问:
函数 DataContainer.initial() 触发 C2280 错误。定义移动分配运算符后,它就可以工作了。但我不清楚为什么它在功能上有效。明显的区别是,它是一个局部变量,是一个类成员。谢谢你的帮助。initial_2()
data_a
data_b
#include <vector>
#include <iostream>
class DataTypeA
{
std::vector<double> data;
public:
// default constructor
DataTypeA() {}
// Move constructor
DataTypeA(DataTypeA&& rhs) noexcept :data(std::move(rhs.data))
{
std::cout << __FUNCTION__ << std::endl;
}
//DataTypeA& operator=(TypeB&& rhs) noexcept
//{
// data = (std::move(rhs.data));
// return *this;
//}
DataTypeA(size_t width, size_t height, double default_val) { data.resize(width * height, default_val); }
size_t get_size() const { return data.size(); }
};
class Reader
{
public:
Reader() {}
DataTypeA read_data()
{
DataTypeA rtn(5, 5, 1.2);
return rtn;
}
};
class DataContainer
{
DataTypeA data_b;
public:
DataContainer() {}
void initial()
{
Reader rd;
// this requires the copy or move assignment operator
// Error C2280 'DataTypeA &DataTypeA::operator =(const DataTypeA &)': attempting to reference a deleted function
data_b = rd.read_data();
}
void initial_2()
{
Reader rd;
DataTypeA data_a = rd.read_data();
std::cout << data_a.get_size();
}
};
答:
在函数中,您将从现有对象创建类型的新对象,因此可以使用移动构造函数。但是,在 中,您正在将新数据分配给现有对象。为此,您需要具有赋值运算符。请参见移动赋值运算符和移动构造函数之间的区别?。initial_2
DataTypeA
initial
当您显式声明移动构造函数时,隐式声明的复制和移动赋值运算符将定义为已删除。
从 C++ 17 标准(15.8.2 复制/移动赋值运算符)
2 如果类定义未显式声明副本 赋值运算符,一个是隐式声明的。如果类 definition 声明 Move 构造函数或 Move 赋值运算符, 隐式声明的复制赋值运算符定义为 已删除;否则,它被定义为默认值 (11.4)。后一种情况 如果类具有用户声明的 copy 构造函数或 用户声明的析构函数。隐式声明的副本分配 类 X 的运算符将具有以下形式
和
4 如果类 X 的定义没有显式声明移动 赋值运算符,如果出现以下情况,则 one 将被隐式声明为默认值 并且仅当
(4.1) — X 没有用户声明的复制构造函数,
(4.2) — X 没有用户声明的移动构造函数,
(4.3) — X 没有用户声明的复制分配运算符,并且
(4.4) — X 没有用户声明的析构函数。
在这份声明中
data_b = rd.read_data();
必须使用赋值运算符(复制或移动赋值运算符,具体取决于定义的赋值运算符),即根据引号被删除。
至于这个记录
DataTypeA data_a = rd.read_data();
那么它就是一个宣言。所以使用了一个构造函数。
评论
DataTypeA data_a = rd.read_data();
data_b = rd.read_data();