如何禁止C++类对象的禁止拷贝操作

如何禁止C++类对象的禁止拷贝操作

类对象禁止拷贝

只需要在将构造函数声明为如下形式即可

class A {
public:
	A() = default;
private:
	A(const A&) = delete;
};

如果使用下面的声明则会报错

int main() {
  A a;
  A b = a;   // compile-time error
}

运行g++编译会报错

main.cpp: In function ‘int main()’:
main.cpp:10:15: error: use of deleted function ‘A::A(const A&)’
   10 |         A b = a;
      |               ^
main.cpp:5:9: note: declared here
    5 |         A(const A&) = delete;
      |         ^

禁止使用操作符=

struct Counter {
  int* p;

  Counter(int v) {
    p = new int(v);
  }

  ~Counter() {
    delete p;
  }
};

int main() {
  Counter a(1);
  Counter b(2);

  a = b;
}

使用gdb调试,设置断点在a=b

(gdb) print a
$1 = {p = 0x55555556aeb0}
(gdb) print *a
No symbol "operator*" in current context.
(gdb) print b
$2 = {p = 0x55555556aed0}

可以看出ab中的成员变量p的值是不同的

现在step next,再看看a和b的值

18      }
(gdb) print a
$7 = {p = 0x55555556aed0}
(gdb) print b
$8 = {p = 0x55555556aed0}

我们可以看到,二者都一样了,即两个变量的成员变量p都指向了同一个地址,地址内的值是2

(gdb) print *a->p
$9 = 2
(gdb) print *b->p
$10 = 2

然后退出主函数之前调用析构函数

(gdb) s
Counter::~Counter (this=0x7fffffffdd00, __in_chrg=<optimized out>) at main.cpp:9
9           delete p;
(gdb) n
10        }
(gdb) print this->p
$13 = (int *) 0x55555556aed0
(gdb) print *this->p
$14 = 1431655786

可以看到地址内的值已被其他的值替换

问题是删除了a的值,那b的值也删除了,原来a的p值并没有被delete

(gdb) print /x *0x55555556aeb0
$17 = 0x1

相当于这里有个指针变量被悬空了,由于C++没有垃圾回收,那么这个内存就一直占据内存,如果数量庞大则会导致内存溢出。

如果要避免这种情况的发生,则可使得运算符设置为不允许拷贝

struct Counter {
  int* p;

  Counter(int v) {
    p = new int(v);
  }

  ~Counter() {
    delete p;
  }

  Counter& operator=(const Counter&) = delete; 
};

int main() {
  Counter a(1);
  Counter b(2);

  a = b;   
}

使用g++进行编译

jx@jx-virtual-machine:~/src/cpp$ g++ main.cpp -o main
main.cpp: In function ‘int main()’:
main.cpp:19:7: error: use of deleted function ‘Counter& Counter::operator=(const Counter&)19 |   a = b;
      |       ^
main.cpp:12:12: note: declared here
   12 |   Counter& operator=(const Counter&) = delete;
      |            ^~~~~~~~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值