从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类

一、深拷贝与浅拷贝

说得简单点,假设一个类有指针成员,如果在拷贝的时候顺带连指针指向的内存也分配了,就称为深拷贝;如果只是分配指针本身的内存,那就是浅拷贝。浅拷贝造成的问题是有两个指针指向同块内存,delete 其中一个指针,那么剩下的指针将成为野指针。编译器合成的默认拷贝构造函数和赋值运算符是浅拷贝的,如果只是普通成员的赋值,浅拷贝也是可以的。

 

 C++ Code 
1
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23
 
#ifndef _STRING_H_

#define _STRING_H_

class String

{

public:

    String(
char *str = 
"");

    ~String();

    String(
const String &other);

    String &
operator=(
const String &other);

    
void Display();

private:

    
char *AllocAndCpy(
char *str);

    
char *str_;

};

#endif 
// _STRING_H_

 

 

 

 C++ Code 

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

 
#include 
"String.h"

//#include <string.h>

#include <cstring>

#include <iostream>

using 
namespace std;

String::String(
char *str
/* = */)

{

    str_ = AllocAndCpy(str);

}

String::~String()

{

    
delete[] str_;

}

String::String(
const String &other)

{

    str_ = AllocAndCpy(other.str_);

}

String &String::
operator =(
const String &other)

{

    
if (
this == &other)

        
return *
this;

    
delete[] str_;

    str_ = AllocAndCpy(other.str_);

    
return *
this;

}

char *String::AllocAndCpy(
char *str)

{

    
int len = strlen(str) + 
1;

    
char *tmp = 
new 
char[len];

    memset(tmp, 
0, len);

    strcpy(tmp, str);

    
return tmp;

}

void String::Display()

{

    cout << str_ << endl;

}

 

 

 

 C++ Code 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

 
#include 
"String.h"

int main(
void)

{

    String s1(
"AAA");

    s1.Display();

    String s2 = s1;     
// 调用拷贝构造函数
    
// 系统提供的默认拷贝构造函数实施的是浅拷贝 s2.str_ = s1.str_


    String s3;

    s3.Display();

    s3 = s2;            
// 调用等号运算符
    
// 系统提供的默认等号运算符实施的是浅拷贝 s3.str_ = s2.str_;
    
// s3.operator=(s2);

s3.Display();

    
// 要让对象是独一无二的,我们要禁止拷贝
    
// 方法是将拷贝构造函数与=运算符声明为私有,并且不提供它们的实现
    
return 
0;

}

从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类

 

上面程序中String 类有一个char* str_ 成员,故实现了深拷贝,这样不会造成内存被释放两次的错误,或者修改指针指向的内存会影响另一个对象的错误。此外,如果我们想让对象是独一无二的,需要禁止拷贝,只需要将拷贝构造函数和等号运算符声明为私有,并且不提供它们的实现。

二、空类

空类默认产生的成员:

class Empty {};
Empty(); // 默认构造函数
Empty( const Empty& );// 默认拷贝构造函数
~Empty(); // 默认析构函数
Empty& operator=( const Empty& );  // 默认赋值运算符
Empty* operator&();              // 取址运算符
const Empty* operator&() const;   // 取址运算符 const

 C++ Code 

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

 
#include <iostream>

using 
namespace std;

class Empty

{

public:

    Empty *
operator&()

    {

        cout << 
"AAAA" << endl;

        
return 
this;

    }

    
const Empty *
operator&() 
const

    {

        cout << 
"BBBB" << endl;

        
return 
this;

    }

};

int main(
void)

{

    Empty e;

    Empty *p = &e;      
// 等价于e.operator&();


    
const Empty e2;

    
const Empty *p2 = &e2;

    cout << 
sizeof(Empty) << endl;

    
return 
0;

}

 

从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类

单步调试一下,可以看到分别调用了两个取地址运算符函数,而且空类的大小为1个字节。

原文链接: https://www.cnblogs.com/jiangu66/p/3159704.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    从零开始学C++之构造函数与析构函数(三):深拷贝与浅拷贝、空类

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/93680

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月10日 上午2:16
下一篇 2023年2月10日 上午2:16

相关推荐