6 c++ deep-copy copy-constructor assignment-operator
我正在处理分配内存供内部使用的对象。目前,它们不可复制。
例如
class MyClass
{
public:
MyClass() { Store = new int; }
~MyClass() { delete Store; }
private:
int* Store;
};
Run Code Online (Sandbox Code Playgroud)
我想添加允许分配所需的内容,既具有复制语义又具有移动语义,并且还能够将它们存储在向量中(具有移动语义)。我不想使用智能指针,并希望保持简单。
我应该定义哪些类成员?如何强制复制分配或移动分配?按值或按引用传递对象时将执行哪个副本?C++ 的连续版本之间的实现会有所不同吗?
例如
MyClass A, B;
A = B; // How to force copy or move ?
std::vector<MyClass> V = { A, B };
Run Code Online (Sandbox Code Playgroud)
您询问了向量,所以...这是 class tbx::Vector。我把它写成练习。其设计遵循Arthur O'Dwyer在 CppCon 2019 上的演讲。请参阅标题为“回归基础:RAII 和零规则”的 YouTube 视频。
为了更密切地关注您询问的复制语义,我只包含了五个“特殊”成员函数,以及其他几个成员和成员函数reserve和swap。虽然类Vector实现了几乎所有的接口std::vector,但是其他的功能这里没有出现。
我留下了一些钩子,您可以在操作符尝试分配失败的情况下插入所需的任何代码new。
这并不打算作为生产代码。首先,为什么要重新发明轮子?其次,有很多优化被省略了。第三,一些功能被省略了,例如,我没有提供完整的ctor补充或对分配器的支持。
template< typename T >
class Vector
{
public:
using value_type = T;
using size_type = std::size_t;
using iterator = value_type*;
using const_iterator = value_type const*;
private:
value_type* data_{ nullptr };
size_type capacity_{};
size_type size_{};
enum : size_type { zero, one };
public:
Vector() noexcept
= default;
explicit Vector(size_type const size)
: data_{ nullptr }, capacity_{ size }, size_{ size }
{
if (zero < size)
{
try { data_ = new value_type[size]; }
catch (std::bad_alloc const&) { throw; }
}
}
Vector (Vector const& that)
: data_{ nullptr }
, capacity_{ that.size_ } // "shrink to fit"
, size_{ that.size_ }
{
if (that.size_ != zero)
{
try { data_ = new value_type[that.size_]; }
catch (std::bad_alloc const&) { throw; }
std::copy(that.data_, that.data_ + size_, data_);
}
}
Vector (Vector&& that) noexcept
: data_ { std::exchange(that.data_, nullptr) }
, capacity_ { std::exchange(that.capacity_, zero) }
, size_ { std::exchange(that.size_, zero) }
{}
~Vector() {
delete[] data_;
}
Vector& operator=(Vector that) noexcept {
swap(that);
return *this;
}
void reserve(size_type const capacity) {
if (capacity_ < capacity) {
value_type* p{ nullptr };
try { p = new value_type[capacity]; }
catch (std::bad_alloc const&) { throw; }
if (data_ != nullptr)
std::copy(data_, data_ + size_, p);
capacity_ = capacity;
std::swap(data_, p);
delete[] p;
}
}
void swap(Vector& that) noexcept {
using std::swap;
swap(capacity_, that.capacity_);
swap(size_, that.size_);
swap(data_, that.data_);
}
friend void swap(Vector& a, Vector& b) noexcept {
a.swap(b);
}
};
Run Code Online (Sandbox Code Playgroud)