📜  C++中的复制构造函数

📅  最后修改于: 2021-05-30 08:42:57             🧑  作者: Mango

我们已经讨论了C++中的构造函数的简介。在本文中,将讨论复制构造函数。
什么是复制构造函数?
复制构造函数是一个成员函数,它使用相同类的另一个对象初始化一个对象。复制构造函数具有以下常规函数原型:

ClassName (const ClassName &old_obj); 

以下是复制构造函数的一个简单示例。

CPP
#include
using namespace std;
 
class Point
{
private:
    int x, y;
public:
    Point(int x1, int y1) { x = x1; y = y1; }
 
    // Copy constructor
    Point(const Point &p1) {x = p1.x; y = p1.y; }
 
    int getX()            {  return x; }
    int getY()            {  return y; }
};
 
int main()
{
    Point p1(10, 15); // Normal constructor is called here
    Point p2 = p1; // Copy constructor is called here
 
    // Let us access values assigned by constructors
    cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
    cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY();
 
    return 0;
}


CPP
MyClass t1, t2;
MyClass t3 = t1;  // ----> (1)
t2 = t1;          // -----> (2)


CPP
#include
#include
using namespace std;
 
class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL); // constructor
    ~String() { delete [] s;  }// destructor
    String(const String&); // copy constructor
    void print() { cout << s << endl; } // Function to print string
    void change(const char *);  // Function to change
};
 
String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
void String::change(const char *str)
{
    delete [] s;
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
String::String(const String& old_str)
{
    size = old_str.size;
    s = new char[size+1];
    strcpy(s, old_str.s);
}
 
int main()
{
    String str1("GeeksQuiz");
    String str2 = str1;
 
    str1.print(); // what is printed ?
    str2.print();
 
    str2.change("GeeksforGeeks");
 
    str1.print(); // what is printed now ?
    str2.print();
    return 0;
}


CPP
#include
#include
using namespace std;
 
class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL); // constructor
    ~String() { delete [] s;  }// destructor
    void print() { cout << s << endl; }
    void change(const char *);  // Function to change
};
 
String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
void String::change(const char *str)
{
    delete [] s;
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
int main()
{
    String str1("GeeksQuiz");
    String str2 = str1;
 
    str1.print(); // what is printed ?
    str2.print();
 
    str2.change("GeeksforGeeks");
 
    str1.print(); // what is printed now ?
    str2.print();
    return 0;
}


输出:

p1.x = 10, p1.y = 15
p2.x = 10, p2.y = 15 

复制构造函数何时调用?
在C++中,在以下情况下可以调用复制构造函数:
1.按值返回类的对象时。
2.当类的对象通过值作为参数传递(传递给函数)时。
3.基于同一类的另一个对象构造一个对象时。
4.编译器生成临时对象时。
但是,不能保证在所有这些情况下都将调用复制构造函数,因为C++标准允许编译器在某些情况下优化复制,一个例子是返回值优化(有时称为RVO)。
资料来源:https://www.geeksforgeeks.org/g-fact-13/什么时候需要用户定义的副本构造函数?
如果我们不定义自己的副本构造函数,则C++编译器会为每个类创建一个默认的副本构造函数,该类在对象之间进行成员级复制。编译器创建的复制构造函数通常可以正常工作。仅当对象具有指针或文件句柄,网络连接等资源的任何运行时分配时,才需要定义我们自己的副本构造函数。
默认构造函数仅执行浅表复制。

浅

只有用户定义的副本构造函数才可以进行深层复制。在用户定义的副本构造函数中,我们确保所复制对象的指针(或引用)指向新的内存位置。

深300x179

复制构造函数与赋值运算符
以下两个语句中的哪一个调用复制构造函数,而哪个调用赋值运算符?

CPP

MyClass t1, t2;
MyClass t3 = t1;  // ----> (1)
t2 = t1;          // -----> (2)

从现有对象创建新对象作为现有对象的副本时,将调用复制构造函数。当已初始化的对象从另一个现有对象中分配了新值时,将调用赋值运算符。在上面的示例中,(1)调用复制构造函数,(2)调用赋值运算符。有关更多详细信息,请参见此内容。
写一个需要复制构造函数的示例类吗?
以下是一个完整的C++程序,以演示Copy构造函数的用法。在下面的String类中,我们必须编写副本构造函数。

CPP

#include
#include
using namespace std;
 
class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL); // constructor
    ~String() { delete [] s;  }// destructor
    String(const String&); // copy constructor
    void print() { cout << s << endl; } // Function to print string
    void change(const char *);  // Function to change
};
 
String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
void String::change(const char *str)
{
    delete [] s;
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
String::String(const String& old_str)
{
    size = old_str.size;
    s = new char[size+1];
    strcpy(s, old_str.s);
}
 
int main()
{
    String str1("GeeksQuiz");
    String str2 = str1;
 
    str1.print(); // what is printed ?
    str2.print();
 
    str2.change("GeeksforGeeks");
 
    str1.print(); // what is printed now ?
    str2.print();
    return 0;
}

输出:

GeeksQuiz
GeeksQuiz
GeeksQuiz
GeeksforGeeks

如果我们从上述代码中删除复制构造函数,那将会是什么问题?
如果从上面的程序中删除copy构造函数,则不会获得预期的输出。对str2所做的更改也反映在str1中,这是意料之外的。

CPP

#include
#include
using namespace std;
 
class String
{
private:
    char *s;
    int size;
public:
    String(const char *str = NULL); // constructor
    ~String() { delete [] s;  }// destructor
    void print() { cout << s << endl; }
    void change(const char *);  // Function to change
};
 
String::String(const char *str)
{
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
void String::change(const char *str)
{
    delete [] s;
    size = strlen(str);
    s = new char[size+1];
    strcpy(s, str);
}
 
int main()
{
    String str1("GeeksQuiz");
    String str2 = str1;
 
    str1.print(); // what is printed ?
    str2.print();
 
    str2.change("GeeksforGeeks");
 
    str1.print(); // what is printed now ?
    str2.print();
    return 0;
}

输出:

GeeksQuiz
GeeksQuiz
GeeksforGeeks
GeeksforGeeks
要从最佳影片策划和实践问题去学习,检查了C++基础课程为基础,以先进的C++和C++ STL课程基础加上STL。要完成从学习语言到DS Algo等的更多准备工作,请参阅“完整面试准备课程”