提问人:DvB 提问时间:2/10/2022 最后编辑:Remy LebeauDvB 更新时间:2/10/2022 访问量:151
我的 Copy and Move 构造函数和赋值运算符出现问题
Problem with my Copy and Move constructor and assignment operators
问:
我想用 C++ 构建自己的完整类。我是这样开始的:Vector
#include <iostream>
#include <initializer_list>
#define Print(x)(std::cout<< x << std::endl)
// Vector Class //
template <typename T>
class Vector
{
// Attributes
int length = 0;
T* array;
public:
// Default constructor
Vector()
: length(0), array(nullptr)
{ }
// Copy constructor
template<typename U>
Vector(const Vector<U>& other)
: Vector(other.len())
{
Print("Use Copy Constructor");
// Coppying other data to new array
array = new T[other.len()];
for (auto i=0; i < other.len(); i++)
array[i] = other[i];
}
// Move constructor
Vector(Vector<T>&& other)
: length(other.len()), array(other.array)
{
Print("Use Move Constructor");
// Deleting other array
other.length = 0;
other.array = nullptr;
}
// Constructor (does not allow uniform initialisation)
Vector(int length)
: length(length), array(new T[length])
{ }
// Constructor (with initialiser list and delegate constructor)
Vector(std::initializer_list<T> list)
: Vector((int)list.size())
{
std::uninitialized_copy(list.begin(), list.end(), array);
}
// Destructor
~Vector()
{
length = 0;
delete[] array;
array = nullptr;
}
// Function Len that returns the length
int len() const
{
return length;
}
// Operator[](int i) and its const overload
auto& operator[](int i)
{
return array[i];
}
auto& operator[](int i) const
{
return array[i];
}
// Copy assignment operator
template<typename U>
Vector& operator=(const Vector<U>& other)
{
Print("Use Copy Operator");
if (this != (Vector*)& other) {
/*
This works the same way but does not solve the problem:
Vector<typename std::common_type<T,U>::type> temp(other);
temp.swap(*this);
*/
delete[] array;
length = other.len();
array = new T[other.len()];
for (auto i = 0; i < other.len(); i++)
array[i] = other[i];
}
return *this;
}
// Move assignment opertator
Vector& operator=(Vector<T>&& other)
{
Print("Use Move Operator");
if (this != (Vector*)&other){
/*
This works the same way but does not solve the problem:
Vector<T> temp(std::move(other)); // moves the array
temp.swap(*this);
*/
delete[] array;
length = other.len();
array = other.array;
other.len() = 0;
other.array = nullptr;
}
return *this;
}
};
但是,如果我现在尝试像这样使用复制分配运算符:
Vector<double> double_vector = {3.4677, 3.212, 2.2, 6.3};
Vector<double> a = double_vector;
我收到以下错误消息:
错误:使用已删除的函数“constexpr Vector<double>::Vector(const Vector<double>&)”
我认为问题出在复制构造函数和复制赋值运算符上,但遗憾的是我找不到解决方案。我觉得奇怪的是,如果我注释掉移动构造函数和移动赋值运算符,代码似乎确实有效。这让我认为编译器很难知道要使用哪个构造函数。但我也可能对此大错特错。
希望我提供了足够的信息来回答/推动正确的方向。
答:
2赞
BoP
2/10/2022
#1
模板从来都不是复制构造函数,而是转换构造函数。
由于您已经定义了一堆其他构造函数,否则默认的复制构造函数将被定义为已删除。
评论
0赞
user4581301
2/10/2022
据我所知,正确的诊断,但我建议添加一个解决方案。
0赞
BoP
2/10/2022
@user4581301 - 我认为第一句话让 OP 添加一个不是模板的复制构造函数变得“明显”。
0赞
user4581301
2/10/2022
我,我会删除模板,但我明白你的意思。使用一些 SFINAE 来确保所包含的类型是可转换的,转换构造函数可能很有用。
下一个:什么是三分法则?
评论
: Vector(other.len())
Vector(int length)
array = new T[other.len()];
template<typename U> Vector(const Vector<U> &other)
Vector(const Vector &other)
Vector
U
Vector
T
Vector