当我学习C++时,人们告诉我要始终至少实施三种方法的规则.
现在我看到新的"... =默认;" 从堆栈溢出的c ++ 0x开始,我的问题是:
是否为这些方法定义了c ++ 11标准实现,还是编译器特定的?
加上我想有一些准确性:
- 在代码方面,实现是什么样的?(如果它是通用的)
- 与我下面的示例实现相比,这是否有优势?
- 如果你不使用赋值/复制构造函数,那么
*... = delete*做什么呢,将它们声明为私有有什么区别?回答(来自@ 40two)- 新的默认值=与旧的默认实现不同吗?
免责声明:当我在我的方法中需要更多高级功能时,我肯定会自己实现它们.但是我习惯于实现赋值运算符和复制构造函数,即使我从未使用它们,只是为了编译器不这样做.
我曾经做过:(编辑,@Drrmmr 交换/移动)
//File T.h
class T
{
public:
T(void);
T(const T &other);
T(const T &&other);
T &operator=(T other);
friend void swap(T &first, T &second);
~T(void);
protected:
int *_param;
};
//File T.cpp
T::T(void) :
_param(std::null)
{}
T::T(T &other)
: _param(other._param)
{}
T::T(T &&other)
: T()
{
swap(*this, other);
}
T &T::operator=(T other)
{
swap(*this, other);
return (*this);
}
friend void swap(T &first, T &second)
{
using std::swap;
swap(first._param, second._param);
}
T::~T(void)
{}
Run Code Online (Sandbox Code Playgroud)
默认行为是:
T()):调用基础 def。演员和成员默认演员。T(const T&)):调用碱基复制。演员和成员复制演员。T(T&&)):调用碱基 move。演员和成员感动演员。T& operator=(const T&)):调用碱基分配。和成员分配。T& operator=(T&&)):呼叫基地转接、会员转接。~T()):调用成员析构函数和基析构函数(相反顺序)。对于内置类型(int 等)
由于指针也是内置类型,因此这适用于int*(而不是它指向的内容)。
现在,如果您不声明任何内容,您的T类将仅保存一个不拥有指向的 int 的 int* ,因此 T 的副本将仅保存指向同一 int 的指针。这与 C++03 的结果行为相同。内置类型的默认实现的移动是复制。对于类是按成员移动(并且取决于成员是什么:只是内置函数的副本)
如果你必须改变这种行为,你必须连贯地做到这一点:例如,如果你想“拥有”你所指向的东西,你需要
nullptr:这定义了一个“空状态”,我们稍后可以参考。
T::T() :_param() {}
T::T(int* s) :_param(s) {}
T(const T& s) :_param(s._param? new int(*s._param): nullptr) {}
~T() { delete _param; } // will do nothing if _param is nullptr
Run Code Online (Sandbox Code Playgroud)
现在,让我们先不定义分配,而是专注于移动:如果您不声明它,因为您声明了副本,它将被删除:这使得 T 对象始终被复制,即使是临时的(与 c 的行为相同) ++03)
但如果源对象是临时的,我们可以创建一个空的目标并交换它们:
T::T(T&& s) :T() { std::swap(_param, s._param); }
Run Code Online (Sandbox Code Playgroud)
这就是所谓的一招。
现在赋值:在 C++11 之前 T& operator=(const T& s)应该检查自赋值,使目标为空并接收指向的副本:
T& operator=(const T& s)
{
if(this == &s) return *this; // we can shortcut
int* p = new int(s._param); //get the copy ...
delete _param; //.. and if succeeded (no exception while copying) ...
_param = p; // ... delete the old and keep the copy
return *this;
}
Run Code Online (Sandbox Code Playgroud)
使用 C++11,我们可以使用参数传递来生成副本,从而给出
T& operator=(T s) //note the signature
{ std::swap(_param, s._param); return *this; }
Run Code Online (Sandbox Code Playgroud)
请注意,这也适用于 C++98,但如果是临时的,则传递副本不会在传递移动中进行优化s。这使得这样的实现在 C++98 和 C++03 中无法盈利,但在 C++11 中却非常方便。
另请注意,无需专门std::swap针对 T:std::swap(a,b);将起作用,以三个动作实现(不是复制)
实现交换函数的实践源于 T 有许多成员的情况,在移动和分配中都需要交换。但它可以是常规的私有成员函数。
| 归档时间: |
|
| 查看次数: |
409 次 |
| 最近记录: |