You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

未实现赋值运算符时构造函数被调用的C++编译器行为解析

关于你遇到的String类赋值行为的底层解释

兄弟,你这个问题其实是C++里隐式类型转换和临时对象在偷偷搞事情!我来给你拆解清楚编译器到底做了什么,以及为啥会出现你看到的现象:

1. 为啥String s; s="Hello World";没报错,还调用了String(const char* _pc)构造函数?

首先,你没给String类重载任何赋值运算符(比如String& operator=(const char*)或者拷贝赋值运算符),但C++编译器会帮你自动生成一个默认的拷贝赋值运算符,签名是String& operator=(const String&)。

当你执行s="Hello World"时,编译器发现右边是const char*类型,和左边的String类型不匹配,它会尝试做隐式类型转换:

  • 用"Hello World"这个const char*作为参数,调用你实现的String(const char* _pc)构造函数,创建一个临时的String对象;
  • 然后调用编译器自动生成的默认拷贝赋值运算符,把这个临时对象的成员变量(capacity和start)浅拷贝给s;
  • 因为这次操作没触发内存重复释放或者野指针这类明显错误(但其实你的代码有浅拷贝隐患,只是这次刚好没炸),所以程序没报错。

2. 为啥析构函数被调用了两次?

这完全是那个临时对象的锅:

  • 第一次析构:赋值操作完成后,那个临时创建的String对象就失去了作用,编译器会自动销毁它,调用一次析构函数;
  • 第二次析构:main函数执行完毕,局部对象s的作用域结束,程序会调用它的析构函数,这就是第二次调用。

顺便提个你的代码小问题

你的析构函数里的逻辑有问题:

if (capacity == 1) delete start;
if (capacity > 1) delete[] start;

不管capacity是1还是更大,你在构造函数里都是用new char[]分配的内存,所以必须统一用delete[]释放,哪怕数组大小是1。用delete去释放new[]分配的内存属于未定义行为,运气好没事,运气差直接崩。

内容的提问来源于stack exchange,提问作者Harsh Patel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:41:50