【发布时间】:2021-12-26 15:49:29
【问题描述】:
作为初学者挑战练习,我正在尝试实现以下内容: 具有属性 (Vec_ptr_cls) 的类:指向向量的指针,方法:构造函数、复制构造函数、移动构造函数、析构函数和 push_back 方法,因为指针是私有的。 具有属性的类 (Data_cls):指向 int 的指针,方法:构造函数、复制构造函数、移动构造函数和析构函数。
预期结果:程序编译,创建 Data_cls 的新对象。创建 Vec_ptr_cls 的新对象,将创建的 Data_cls 对象推回。 实际结果:程序无法编译。错误信息:使用已删除的函数 'constexpr Data_cls& Data_cls::operator=(const Data_cls&)'。
我已经尝试在 StackOverflow 上搜索并检查答案,我认为要么我没有必要的知识来理解它们,要么它们不适用于这种特殊情况(它们中的大多数与 const 属性有关一些课程,据我所知,我没有)。我试图剪掉一些零碎的东西,似乎 Data_cls 的移动构造函数有问题,但我不明白为什么或如何。编译器错误声称复制构造函数已被删除,但是我已经声明了自己的,这还不够好吗?编辑:正如 Nathan Pierson 所指出的,编译器实际上是在抱怨赋值运算符,而不是复制构造函数。我在这里更难过。
这是复制我遇到的问题的原型代码:
#include <iostream>
#include <vector>
class Data_cls
{
private:
int *d;
public:
Data_cls(int num)
{
d = new int;
*d = num;
}
Data_cls(const Data_cls &source)
{
d = new int;
*d = *source.d;
}
Data_cls(Data_cls &&source)
{
d = source.d;
source.d = nullptr;
}
~Data_cls()
{
delete d;
}
};
class Vec_ptr_cls
{
private:
std::vector <Data_cls> *vec;
public:
Vec_ptr_cls()
{
vec = new std::vector <Data_cls>;
*vec = {};
}
Vec_ptr_cls(const Vec_ptr_cls &source)
{
vec = new std::vector <Data_cls>;
*vec = *source.vec;
}
Vec_ptr_cls(Vec_ptr_cls &&source)
{
vec = source.vec;
source.vec = nullptr;
}
~Vec_ptr_cls()
{
delete vec;
}
void add_new(Data_cls d)
{
(*vec).push_back(d);
}
};
int main()
{
Data_cls test_d{20};
Data_cls test_dd{30};
Data_cls test_ddd{40};
Vec_ptr_cls tmp_vec{};
tmp_vec.add_new(test_d);
tmp_vec.add_new(test_dd);
tmp_vec.add_new(test_ddd);
return 0;
}
我在尝试实现一些更复杂的东西(电影列表和电影对象)作为练习时遇到了这个问题,我发现有趣的是,即使简化为这个简单的版本,它也不起作用。我希望我的问题没有说得不好,很好奇为什么这不起作用。
【问题讨论】:
-
你的 C++ 教科书的章节主题是什么?了解正在学习的主题将有助于指出问题所在。
-
Tangential:
delete[] vec;in~Vec_ptr_cls不正确。你没有使用new[]创建vec,你不应该使用delete[]来销毁它。 -
另外编译器错误不是抱怨副本 constructor 被删除,而是抱怨副本 assignment operator 被删除。
-
@SamVarshavchik 这是关于类和对象的一般章节。这一章还介绍了构造函数、复制构造函数和移动构造函数(这是 Tim Buchalka 的 Udemy 课程)。没有指针,这就是本章练习的结尾。在解决方案视频的最后,讲师提出了一个挑战,即用指针作为属性而不是非 ptr 数据类型来重新制作整个练习。 @NathanPierson 啊,谢谢,没错,我应该使用
delete。在赋值运算符部分,嗯,这是正确的,我的错误。 -
"[class.copy.assign]/2 ... 如果类定义声明了移动构造函数或移动赋值运算符,则隐式声明的复制赋值运算符定义为删除..." 由于您已经为您的类提供了一个移动构造函数,因此您还必须提供一个复制赋值运算符;并且可能还想提供移动分配。
标签: c++ class pointers vector move-constructor