专业编程基础技术教程

网站首页 > 基础教程 正文

C/C++编程笔记:详细讲解丨复制构造函数

ccvgpt 2024-10-12 13:50:16 基础教程 6 ℃

什么是复制构造函数?

复制构造函数是一个成员函数,它使用相同类的另一个对象初始化一个对象。复制构造函数具有以下常规函数原型:

C/C++编程笔记:详细讲解丨复制构造函数

ClassName(const ClassName&old_obj);

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

#include<iostream>

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;

}

输出:

p1.x = 10, p1.y = 15

p2.x = 10, p2.y = 15


复制构造函数何时 调用?

在C ++中,在以下情况下可以调用复制构造函数:

1.当类的对象按值返回时。

2.当类的对象通过值作为参数传递(传递给函数)时。

3.基于同一类的另一个对象构造一个对象时。

4.编译器生成临时对象时。

但是,不能保证在所有这些情况下都将调用复制构造函数,因为C ++标准允许编译器在某些情况下优化复制,一个例子是返回值优化(有时称为RVO)。

当是一个需要用户定义的副本构造函数吗?

如果我们不定义自己的副本构造函数,则C ++编译器会为每个类创建一个默认的副本构造函数,该类在对象之间进行成员级复制。编译器创建的复制构造函数通常可以正常工作。仅当对象具有指针或文件句柄,网络连接等资源的任何运行时分配时,才需要定义我们自己的副本构造函数。

默认构造函数仅执行浅表复制。

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

复制构造函数与赋值运算符

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

MyClass t1, t2;

MyClass t3 = t1; // ----> (1)

t2 = t1; // -----> (2)

从现有对象创建新对象作为现有对象的副本时,将调用复制构造函数。当已初始化的对象从另一个现有对象中分配了新值时,将调用赋值运算符。在上面的示例中,(1)调用复制构造函数,(2)调用赋值运算符。

写一个需要复制构造函数的示例类吗?

以下是一个完整的C ++程序,以演示Copy构造函数的用法。在下面的String类中,我们必须编写副本构造函数。

#include<iostream>

#include<cstring>

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中,这是意料之外的。

#include<iostream>

#include<cstring>

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

我们可以将复制构造函数设为私有吗?

是的,可以将复制构造函数设为私有。当我们在一个类中将复制构造函数设为私有时,该类的对象将变为不可复制。当我们的类具有指针或动态分配的资源时,这特别有用。在这种情况下,我们可以像上面的String示例一样编写我们自己的副本构造函数,也可以创建一个私有副本构造函数,以便用户获得编译器错误,而不是在运行时感到意外。

为什么必须将复制构造函数的参数作为引用传递?

按值传递对象时,将调用复制构造函数。复制构造函数本身就是一个函数。因此,如果我们在复制构造函数中按值传递参数,则将调用复制构造函数来调用复制构造函数,这将成为一个无终止的调用链。因此,编译器不允许参数按值传递。

以上就是今天的全部内容了。每日分享小知识,希望对你有帮助~

另外如果你想更好的提升你的编程能力,学好C语言C++编程!弯道超车,快人一步!笔者这里或许可以帮到你~

编程学习书籍分享:

编程学习视频分享:

分享(源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

点击下方【了解更多】获取更多学习资料帮助你学习成长哦~

最近发表
标签列表