gpt4 book ai didi

详解C++ 拷贝构造函数

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章详解C++ 拷贝构造函数由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

  • 通过使用另一个同类型的对象来初始化新创建的对象。
  • 复制对象把它作为参数传递给函数。
  • 复制对象,并从函数返回这个对象。

如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:

?
1
2
3
classname ( const classname &obj) {
   // 构造函数的主体
}

在这里,obj 是一个对象引用,该对象是用于初始化另一个对象的.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
 
using namespace std;
 
class Line
{
   public :
    int getLength( void );
    Line( int len );       // 简单的构造函数
    Line( const Line &obj);   // 拷贝构造函数
    ~Line();           // 析构函数
 
   private :
    int *ptr;
};
 
// 成员函数定义,包括构造函数
Line::Line( int len)
{
   cout << "调用构造函数" << endl;
   // 为指针分配内存
   ptr = new int ;
   *ptr = len;
}
 
Line::Line( const Line &obj)
{
   cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
   ptr = new int ;
   *ptr = *obj.ptr; // 拷贝值
}
 
Line::~Line( void )
{
   cout << "释放内存" << endl;
   delete ptr;
}
int Line::getLength( void )
{
   return *ptr;
}
 
void display(Line obj)
{
   cout << "line 大小 : " << obj.getLength() <<endl;
}
 
// 程序的主函数
int main( )
{
   Line line(10);
 
   display(line);
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

调用构造函数 调用拷贝构造函数并为指针 ptr 分配内存 line 大小 : 10 释放内存 释放内存 。

下面的实例对上面的实例稍作修改,通过使用已有的同类型的对象来初始化新创建的对象:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
 
using namespace std;
 
class Line
{
   public :
    int getLength( void );
    Line( int len );       // 简单的构造函数
    Line( const Line &obj);   // 拷贝构造函数
    ~Line();           // 析构函数
 
   private :
    int *ptr;
};
 
// 成员函数定义,包括构造函数
Line::Line( int len)
{
   cout << "调用构造函数" << endl;
   // 为指针分配内存
   ptr = new int ;
   *ptr = len;
}
 
Line::Line( const Line &obj)
{
   cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
   ptr = new int ;
   *ptr = *obj.ptr; // 拷贝值
}
 
Line::~Line( void )
{
   cout << "释放内存" << endl;
   delete ptr;
}
int Line::getLength( void )
{
   return *ptr;
}
 
void display(Line obj)
{
   cout << "line 大小 : " << obj.getLength() <<endl;
}
 
// 程序的主函数
int main( )
{
   Line line1(10);
 
   Line line2 = line1; // 这里也调用了拷贝构造函数
 
   display(line1);
   display(line2);
 
   return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

调用构造函数 调用拷贝构造函数并为指针 ptr 分配内存 调用拷贝构造函数并为指针 ptr 分配内存 line 大小 : 10 释放内存 调用拷贝构造函数并为指针 ptr 分配内存 line 大小 : 10 释放内存 释放内存 释放内存 。

关于为什么当类成员中含有指针类型成员且需要对其分配内存时,一定要有总定义拷贝构造函数??

默认的拷贝构造函数实现的只能是浅拷贝,即直接将原对象的数据成员值依次复制给新对象中对应的数据成员,并没有为新对象另外分配内存资源.

这样,如果对象的数据成员是指针,两个指针对象实际上指向的是同一块内存空间.

在某些情况下,浅拷贝回带来数据安全方面的隐患.

当类的数据成员中有指针类型时,我们就必须定义一个特定的拷贝构造函数,该拷贝构造函数不仅可以实现原对象和新对象之间数据成员的拷贝,而且可以为新的对象分配单独的内存资源,这就是深拷贝构造函数.

如何防止默认拷贝发生 。

声明一个私有的拷贝构造函数,这样因为拷贝构造函数是私有的,如果用户试图按值传递或函数返回该类的对象,编译器会报告错误,从而可以避免按值传递或返回对象.

总结:

当出现类的等号赋值时,会调用拷贝函数,在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。所以,这时,必须采用深拷贝.

深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝.

以上就是详解C++ 拷贝构造函数的详细内容,更多关于C++ 拷贝构造函数的资料请关注我其它相关文章! 。

原文链接:https://www.runoob.com/cplusplus/cpp-copy-constructor.html 。

最后此篇关于详解C++ 拷贝构造函数的文章就讲到这里了,如果你想了解更多关于详解C++ 拷贝构造函数的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com