提问人:KcFnMi 提问时间:10/6/2022 更新时间:10/7/2022 访问量:79
尝试在 operator= 上使用复制和交换习语
Trying to use copy and swap idiom on operator=
问:
在尝试实现 MyVector 时,我最终得到:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
class MyVector
{
int m_size = 0;
int m_capacity = 0;
T* m_data = nullptr;
public:
MyVector()
{
cout << "defautl ctor" << endl;
realloc(2);
}
MyVector(const MyVector& v)
: m_size(v.m_size),
m_capacity(v.m_capacity)
{
cout << "copy ctor" << endl;
m_data = new T[m_size];
*m_data = *v.m_data;
}
MyVector(MyVector&& v)
: m_size(v.m_size),
m_capacity(v.m_capacity)
{
cout << "move ctor" << endl;
m_data = move(v.m_data);
v.m_data = nullptr;
v.m_size = 0;
v.m_capacity = 0;
}
MyVector& operator= (const MyVector& v)
{
cout << "copy assignment operator" << endl;
// m_size = v.m_size;
// m_capacity = v.m_capacity;
// *m_data = *v.m_data;
MyVector<int> copy = v;
swap(*this, copy);
return *this;
}
void push_back(const T& value)
{
if (!(m_size < m_capacity))
{
// cout << value << " size is " << m_size << " capacity is " << m_capacity << endl;
realloc(m_size*2);
// return;
}
m_data[m_size++] = value;
}
T& operator[] (int index)
{
cout << "index " << index << " of size " << m_size << endl;
if (!(index < m_size))
cout << "index out of bounds" << endl;
return m_data[index];
}
int size()
{
return m_size;
}
T* begin()
{
return &m_data[0];
}
T* end()
{
return &m_data[size()];
}
private:
void realloc(int new_capacity)
{
// cout << __func__ << " new capacity " << new_capacity << endl;
T* data = new T[new_capacity];
for (int i = 0; i < m_size; i++)
data[i] = m_data[i];
delete[] m_data;
m_data = data;
m_capacity = new_capacity;
}
};
int main(int argc, char** argv)
{
cout << "starting..." << endl;
MyVector<int> a;
a.push_back(7);
MyVector<int> d;
d = a;
cout << a[0] << endl;
cout << d[0] << endl;
return 0;
}
在哪里operator=
MyVector& operator= (const MyVector& v)
{
cout << "copy assignment operator" << endl;
// m_size = v.m_size;
// m_capacity = v.m_capacity;
// *m_data = *v.m_data;
MyVector<int> copy = v; // copy and swap
swap(*this, copy);
return *this;
}
然而,这导致了一种似乎是递归的行为。那么,我对复制和交换方法的理解是错误的吗?还是我错过了什么?
答:
2赞
Remy Lebeau
10/7/2022
#1
如注释中所述,您没有为 实现函数,因此该语句正在调用(使用 的众多陷阱之一),这将再次调用您的,因此您看到的递归行为。swap()
MyVector
swap(*this, copy);
std::swap()
using namespace std;
operator=
此外,您的复制构造函数未正确实现。它不会将输入数组中的所有元素复制到新数组中。它只复制第一个元素。
此外,您缺少一个析构函数来释放分配的数组。
此外,由于同时具有复制和移动构造函数,因此您的两个赋值可以(并且应该)合并为一个采用 by 值的运算符。这样,编译器就可以根据调用方是分别传入左值还是右值来决定是使用 copy 还是 move 语义来调用运算符。然后,运算符可以随心所欲地输入任何给定的内容,因为在输入运算符之前,输入已经被复制或移动了。MyVector
operator=
MyVector
swap
尝试更多类似的东西:
#include <iostream>
#include <string>
#include <algorithm>
#include <stdexcept>
template <typename T>
class MyVector
{
int m_size = 0;
int m_capacity = 0;
T* m_data = nullptr;
public:
MyVector()
{
std::cout << "default ctor" << std::endl;
realloc(2);
}
MyVector(const MyVector& v)
{
std::cout << "copy ctor" << std::endl;
realloc(v.m_capacity);
std::copy_n(v.m_data, v.m_size, m_data);
m_size = v.m_size;
}
MyVector(MyVector&& v)
{
std::cout << "move ctor" << std::endl;
v.swap(*this);
}
~MyVector()
{
std::cout << "dtor" << std::endl;
delete[] m_data;
}
MyVector& operator= (MyVector v)
{
std::cout << "assignment operator" << std::endl;
v.swap(*this);
return *this;
}
void push_back(const T& value)
{
if (m_size >= m_capacity)
{
// std::cout << value << " size is " << m_size << " capacity is " << m_capacity << std::endl;
realloc(m_size * 2);
}
m_data[m_size] = value;
++m_size;
}
T& operator[] (int index)
{
std::cout << "index " << index << " of size " << m_size << std::endl;
if (index < 0 || index >= m_size)
throw std::out_of_range("index out of bounds");
return m_data[index];
}
int size() const
{
return m_size;
}
T* begin()
{
return &m_data[0];
}
T* end()
{
return &m_data[m_size];
}
void swap(MyVector &other)
{
std::swap(m_data, other.m_data);
std::swap(m_size, other.m_size);
std::swap(m_capacity, other.m_capacity);
}
private:
void realloc(int new_capacity)
{
// std::cout << __func__ << " new capacity " << new_capacity << std::endl;
T* data = new T[new_capacity];
std::copy_n(m_data, m_size, data);
std::swap(m_data, data);
m_capacity = new_capacity;
delete[] data;
}
};
// for std::swap() to use via ADL...
void swap(MyVector &v1, MyVector &v2)
{
v1.swap(v2);
}
评论
0赞
KcFnMi
10/7/2022
关于合并,如果我选择不合并它,那么替代方案可能是拥有和具有相同的身体?operator=
MyVector& operator= (const MyVecto&r v)
MyVector& operator= (MyVector&& v)
0赞
Remy Lebeau
10/7/2022
@KcFnMi它们会有相似的代码,但不是完全相同的代码,例如:MyVector& operator= (const MyVector &v) { if (&v != this) { MyVector temp(v); temp.swap(*this); } return *this; } MyVector& operator= (MyVector &&v) { MyVector temp(std::move(v)); temp.swap(*this); return *this; }
评论
swap
MyVector
std::swap
std::swap
使用,因此是递归。这让你感到惊讶吗?MyVector::operator=
std::swap
MyVector temp = a; a = b; b = a;
operator=
MyVector& operator= (const MyVector& v)
MyVector& operator= (MyVector v)
MyVector<int> copy = v; // copy and swap