Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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++_Copy Constructor - Fatal编程技术网

什么时候我们必须使用复制构造函数? 我知道C++编译器为类创建了一个复制构造函数。在哪种情况下,我们必须编写一个用户定义的复制构造函数?你能举几个例子吗

什么时候我们必须使用复制构造函数? 我知道C++编译器为类创建了一个复制构造函数。在哪种情况下,我们必须编写一个用户定义的复制构造函数?你能举几个例子吗,c++,copy-constructor,C++,Copy Constructor,编译器生成的复制构造函数执行成员复制。有时这是不够的。例如: class Class { public: Class( const char* str ); ~Class(); private: char* stored; }; Class::Class( const char* str ) { stored = new char[srtlen( str ) + 1 ]; strcpy( stored, str ); } Class::~Class()

编译器生成的复制构造函数执行成员复制。有时这是不够的。例如:

class Class {
public:
    Class( const char* str );
    ~Class();
private:
    char* stored;
};

Class::Class( const char* str )
{
    stored = new char[srtlen( str ) + 1 ];
    strcpy( stored, str );
}

Class::~Class()
{
    delete[] stored;
}
在这种情况下,以成员方式复制存储的
成员不会复制缓冲区(只复制指针),因此共享缓冲区的第一个要销毁的副本将成功调用
delete[]
,第二个将运行未定义的行为。您需要深度复制复制构造函数(以及赋值运算符)


如果您有一个动态分配内容的类。例如,您将一本书的标题存储为char*,并将标题设置为new,copy将不起作用


您必须编写一个复制构造函数,该构造函数执行
title=new char[length+1]
,然后执行
strcpy(title,titleIn)
。复制构造函数只进行“浅层”复制。

当对象按值传递、按值返回或显式复制时,将调用复制构造函数。如果没有复制构造函数,C++创建一个默认拷贝构造器,它创建浅拷贝。如果对象没有指向动态分配内存的指针,那么浅拷贝就可以了。

我有点恼火,因为没有引用
五个规则

这条规则非常简单:

五法则:
无论何时编写析构函数、复制构造函数、复制赋值运算符、移动构造函数或移动赋值运算符中的任何一个,都可能需要编写其他四个

但是,您应该遵循一个更一般的指导原则,它源于编写异常安全代码的需要:

每个资源都应该由专用对象管理

在这里,
@sharptooth
的代码仍然(大部分)很好,但是如果他向他的类添加第二个属性,则不会。考虑下面的类:

class Erroneous
{
public:
  Erroneous();
  // ... others
private:
  Foo* mFoo;
  Bar* mBar;
};

Erroneous::Erroneous(): mFoo(new Foo()), mBar(new Bar()) {}
如果
newbar
抛出,会发生什么情况?如何删除
mFoo
指向的对象?有一些解决方案(功能级别的try/catch…),但它们无法扩展

处理这种情况的正确方法是使用适当的类而不是原始指针

class Righteous
{
public:
private:
  std::unique_ptr<Foo> mFoo;
  std::unique_ptr<Bar> mBar;
};

我不知道你的情况,但我觉得我的更容易;)

禁用copy-ctor和operator=通常是个好主意,除非类特别需要它。这可以防止低效率,例如在预期引用时按值传递参数。此外,编译器生成的方法可能无效。

我可以回忆我的实践,并考虑以下情况,即必须显式声明/定义复制构造函数。我将这些案件分为两类

  • 正确性/语义-如果不提供用户定义的复制构造函数,则使用该类型的程序可能无法编译,或可能无法正常工作
  • 优化-为编译器生成的复制构造函数提供了一个很好的替代方案,可以使程序更快


正确性/语义 我在本节中介绍了声明/定义复制构造函数对于使用该类型的程序的正确操作是必要的情况

阅读本节之后,您将了解允许编译器自己生成复制构造函数的几个陷阱。因此,正如在his中所指出的,关闭新类的可复制性并在以后真正需要时故意启用它总是安全的

如何在C++03中使类不可复制 声明一个私有复制构造函数,而不为其提供实现(这样,即使该类型的对象是在类自己的作用域中复制的,或者是由它的朋友复制的,构建也会在链接阶段失败)

如何在C++11或更新版本中使类不可复制 用结尾处的
=delete
声明复制构造函数


浅拷贝与深拷贝 这是最容易理解的案例,实际上是其他答案中提到的唯一案例。我做得很好。我只想补充一点,应该由对象独占的深度复制资源可以应用于任何类型的资源,动态分配内存只是其中的一种。如果需要,深度复制对象也可能需要

  • 复制磁盘上的临时文件
  • 打开单独的网络连接
  • 创建单独的工作线程
  • 分配单独的OpenGL帧缓冲区

自注册对象 考虑一个类,其中所有对象——无论它们是如何构造的——都必须以某种方式注册。一些例子:

  • 最简单的示例:维护当前现有对象的总数。对象注册只是增加静态计数器

  • 一个更复杂的例子是有一个单例注册表,其中存储对该类型的所有现有对象的引用(以便可以向所有对象发送通知)

  • 引用计数的智能指针可以看作是这类指针中的一个特例:新指针将自己“注册”到共享资源中,而不是在全局注册表中

这种自注册操作必须由该类型的任何构造函数执行,复制构造函数也不例外


具有内部交叉引用的对象 一些对象可能具有非平凡的内部结构,在其不同的子对象之间具有直接的交叉引用(事实上,仅一个这样的内部交叉引用就足以触发这种情况)。编译器提供的复制构造函数将打破内部对象内部关联,将它们转换为对象间关联

例如:

struct MarriedMan;
struct MarriedWoman;

struct MarriedMan {
    // ...
    MarriedWoman* wife;   // association
};

struct MarriedWoman {
    // ...
    MarriedMan* husband;  // association
};

struct MarriedCouple {
    MarriedWoman wife;    // aggregation
    MarriedMan   husband; // aggregation

    MarriedCouple() {
        wife.husband = &husband;
        husband.wife = &wife;
    }
};

MarriedCouple couple1; // couple1.wife and couple1.husband are spouses

MarriedCouple couple2(couple1);
// Are couple2.wife and couple2.husband indeed spouses?
// Why does couple2.wife say that she is married to couple1.husband?
// Why does couple2.husband say that he is married to couple1.wife?

仅允许满足特定条件的对象
class Class
{
public:
  Class(char const* str): mData(str) {}
private:
  std::string mData;
};
struct MarriedMan;
struct MarriedWoman;

struct MarriedMan {
    // ...
    MarriedWoman* wife;   // association
};

struct MarriedWoman {
    // ...
    MarriedMan* husband;  // association
};

struct MarriedCouple {
    MarriedWoman wife;    // aggregation
    MarriedMan   husband; // aggregation

    MarriedCouple() {
        wife.husband = &husband;
        husband.wife = &wife;
    }
};

MarriedCouple couple1; // couple1.wife and couple1.husband are spouses

MarriedCouple couple2(couple1);
// Are couple2.wife and couple2.husband indeed spouses?
// Why does couple2.wife say that she is married to couple1.husband?
// Why does couple2.husband say that he is married to couple1.wife?
class base{
    int a, *p;
public:
    base(){
        p = new int;
    }
    void SetData(int, int);
    void ShowData();
    base(const base& old_ref){
        //No coding present.
    }
};
void base :: ShowData(){
    cout<<this->a<<" "<<*(this->p)<<endl;
}
void base :: SetData(int a, int b){
    this->a = a;
    *(this->p) = b;
}
int main(void)
{
    base b1;
    b1.SetData(2, 3);
    b1.ShowData();
    base b2 = b1; //!! Copy constructor called.
    b2.ShowData();
    return 0;
}
Output: 
2 3 //b1.ShowData();
1996774332 1205913761 //b2.ShowData();