Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 减少运算符=和复制构造函数之间的代码重复_C++_Dry_Copy Constructor_Assignment Operator - Fatal编程技术网

C++ 减少运算符=和复制构造函数之间的代码重复

C++ 减少运算符=和复制构造函数之间的代码重复,c++,dry,copy-constructor,assignment-operator,C++,Dry,Copy Constructor,Assignment Operator,我有一个类,它需要一个非默认的复制构造函数和赋值运算符(它包含指针列表)。是否有任何常规方法可以减少复制构造函数和赋值运算符之间的代码重复 将公共代码分解为私有成员函数。一个简单(相当做作)的例子: #包括 课堂测试 { 公众: 测试(常量字符*n) { 名称=新字符[20]; strcpy(名称,n); } ~Test() { 删除[]名称; } //复制构造函数 测试(常数测试与测试) { std::cout没有“通用方法”来编写在所有情况下都能工作的自定义复制构造函数和赋值运算符。但是有一

我有一个类,它需要一个非默认的复制构造函数和赋值运算符(它包含指针列表)。是否有任何常规方法可以减少复制构造函数和赋值运算符之间的代码重复

将公共代码分解为私有成员函数。一个简单(相当做作)的例子:

#包括
课堂测试
{
公众:
测试(常量字符*n)
{
名称=新字符[20];
strcpy(名称,n);
}
~Test()
{
删除[]名称;
}
//复制构造函数
测试(常数测试与测试)
{
std::cout没有“通用方法”来编写在所有情况下都能工作的自定义复制构造函数和赋值运算符。但是有一种称为“复制-交换”的习惯用法:

它在许多(但不是所有)情况下都很有用。有时你可以做得更好。向量或字符串可以有更好的分配,如果它足够大,可以重用分配的存储

My &My::operator = (My temp)  // thanks, sellibitze
{
    swap (*this, temp);
    return *this;
}

并实现一个专门的
std::swap(My&,My&)

,正如许多海报已经指出的那样,让operator=创建一个新的 对象,然后使用swap是一种常用的技术,它不必在operator=中复制代码

也就是说,我想指出这种技术的一些优点和缺点,以帮助您决定它是否合适

亲例外安全

如果您的对象具有可能导致抛出的资源需求,并且假设swap不会抛出,则此技术提供了异常安全性的有力保证(被分配到的对象具有另一个对象的值,或者该对象保持不变)

资源足迹


这项技术的一个问题是,它需要在旧对象发布之前创建一个完整的新对象。如果您的对象需要大量资源,这可能是一个问题。

我认为您应该能够在操作符内调用复制构造函数=这里有一些答案:+1-我认为复制交换的简要总结很好。也很好关于重用存储的想法。您可能想指出运算符=和更标准的const myclass&operator=(const myclass&other)之间的微妙之处;swap()可能应该标记为nothrow。Bills comment上也是如此。更多的解释会更好。另外请注意:>swap应该是一个自由函数“void swap”(myclass&,myclass&)'>您仍然需要在swap中枚举所有属性,而不是在赋值中枚举它们operator@kevinarpe:无特殊。
swap(复制)
也有效。有时我写
这个->
是为了更明确地说明它是一个数据成员或成员函数。这就是复制和交换现在应该是什么样子。你正在显式地创建一个副本,否则可能会被忽略。这里有一篇关于这方面的文章:正如Dave注意到的,alexandrescu在6年前发现了这一点y:读起来也很有趣!嗯,顺便说一句,这张海报也叫戴夫。我很抱歉搞混了——我是说cpp的戴夫·亚伯拉罕(下一个:)Alexandrescu的那篇文章真的很有帮助。内存泄漏!MakeDeepCopy忽略了名称已经指向已分配内存的可能性。但遗憾的是,复制构造函数不能使用成员初始值设定项,这样做……请注意,
t2=t2
将无法使用所编写的赋值运算符。(例如,如果要对它们的数组进行排序,则需要考虑这一点。)再补充一点:我认为重用是不适用的。创建新对象和只分配给它是有区别的。在简单的成员分配就足够的情况下,不需要自定义复制构造函数和分配运算符。如果您必须做更高级的事情(即管理分配的内存)复制和分配之间的相似性接近于零。@Vijay:但是现在你忘记了初始化复制构造的“名称”,这在某种程度上证明了我的观点。当涉及到显式资源管理时,复制构造和复制分配做不同的事情。重用的可能性很小。
 class myclass
 {
    ...
 public:
    myclass(myclass const&);

    void swap(myclass & with);

    myclass& operator=(myclass copy) {
        this->swap(copy);
        return *this;
    }

    ...
};
My &My::operator = (My temp)  // thanks, sellibitze
{
    swap (*this, temp);
    return *this;
}