C++构造/析构函数操作静态变量异常:创建对象后计数为0
Owner类静态计数变量最终为0的原因及解决方法
问题场景
我定义了Owner类用于存储所有者信息,通过静态变量amountOfOwners统计已创建的所有者总数——构造函数中对其递增,析构函数中递减。但创建3个Owner对象后,该静态变量的值最终为0。
Owner类代码
class Owner { std::string fullname; std::string inn; std::vector<Property*> properties; int amountOfProperty; public: static int amountOfOwners; Owner(const std::string& fullname, const std::string& inn); ~Owner(); void addProperty(Property *p); void removeProperty(const Property* p); }; Owner::Owner(const std::string& fullname, const std::string& inn) { this->fullname = fullname; this->inn = inn; amountOfProperty = 0; amountOfOwners++; } Owner::~Owner() { amountOfOwners--; } void Owner::addProperty(Property* p) { properties.push_back(p); amountOfProperty++; } void Owner::removeProperty(const Property* property) { auto it = std::find(properties.begin(), properties.end(), property); if (it != properties.end()) { properties.erase(it); amountOfProperty--; } }
main函数代码
#include <iostream> #include "Property.h" #include "Appartment.h" #include "Car.h" #include "CountryHouse.h" #include "Owner.h" using namespace std; int Owner::amountOfOwners = 0; int main() { std::vector<Owner> owners; char choice; Owner owner1("John Doe", "123456789012"); owner1.addProperty(new Appartment(100000, 80)); owner1.addProperty(new Car(50000, 200)); owner1.addProperty(new CountryHouse(200000, 50)); Owner owner2("Jane Smith", "987654321098"); owner2.addProperty(new Appartment(150000, 100)); owner2.addProperty(new Car(60000, 250)); owner2.addProperty(new CountryHouse(300000, 70)); Owner owner3("Mike Johnson", "456789012345"); owner3.addProperty(new Appartment(120000, 90)); owner3.addProperty(new Car(55000, 220)); owner3.addProperty(new CountryHouse(250000, 60)); owners.push_back(owner1); owners.push_back(owner2); owners.push_back(owner3); cout << Owner::amountOfOwners; return 0; }
原因分析
问题核心在于默认拷贝构造未处理静态计数,且vector扩容时会销毁旧的拷贝对象:
- 创建
owner1、owner2、owner3三个栈对象,每个对象构造时amountOfOwners递增,此时计数为3。 - 执行
owners.push_back(owner1):vector初始为空,分配容量1,通过默认拷贝构造创建owner1的副本存入vector——但未重载拷贝构造函数,副本构造不会触发amountOfOwners递增,计数仍为3。 - 执行
owners.push_back(owner2):vector容量不足触发扩容:- 销毁vector中已有的1个拷贝对象,触发析构函数,
amountOfOwners减1变为2; - 分配新空间,拷贝原有的1个对象和
owner2的副本,拷贝过程未递增计数,计数保持2。
- 销毁vector中已有的1个拷贝对象,触发析构函数,
- 执行
owners.push_back(owner3):vector再次扩容:- 销毁vector中已有的2个拷贝对象,触发两次析构,
amountOfOwners减2变为0; - 分配新空间,拷贝原有的2个对象和
owner3的副本,拷贝仍未递增计数,计数保持0。
- 销毁vector中已有的2个拷贝对象,触发两次析构,
- 此时执行输出语句,得到的
amountOfOwners即为0。
解决方案
思路一:禁用拷贝,使用原地构造或移动语义
避免对象拷贝,直接在vector中构造Owner对象,或使用移动语义转移所有权,消除不必要的拷贝和销毁:
// 在Owner类中禁用拷贝构造和拷贝赋值运算符(C++11及以上) class Owner { // ... 原有成员 ... public: // ... 原有成员 ... Owner(const Owner&) = delete; Owner& operator=(const Owner&) = delete; // 可选:启用移动构造和移动赋值 Owner(Owner&&) = default; Owner& operator=(Owner&&) = default; }; // 修改main函数,直接在vector中构造对象 int main() { std::vector<Owner> owners; // 使用emplace_back直接在vector内存中构造对象,避免拷贝 owners.emplace_back("John Doe", "123456789012"); owners.back().addProperty(new Appartment(100000, 80)); owners.back().addProperty(new Car(50000, 200)); owners.back().addProperty(new CountryHouse(200000, 50)); owners.emplace_back("Jane Smith", "987654321098"); owners.back().addProperty(new Appartment(150000, 100)); owners.back().addProperty(new Car(60000, 250)); owners.back().addProperty(new CountryHouse(300000, 70)); owners.emplace_back("Mike Johnson", "456789012345"); owners.back().addProperty(new Appartment(120000, 90)); owners.back().addProperty(new Car(55000, 220)); owners.back().addProperty(new CountryHouse(250000, 60)); cout << Owner::amountOfOwners; // 此时输出3 return 0; }
思路二:重载拷贝构造和拷贝赋值,处理静态计数
若必须保留拷贝功能,需重载拷贝构造函数同步更新静态计数,同时处理properties指针的深拷贝(避免重复释放内存):
// 重载拷贝构造函数 Owner::Owner(const Owner& other) { this->fullname = other.fullname; this->inn = other.inn; this->amountOfProperty = other.amountOfProperty; // 深拷贝properties中的指针,需为Property类添加clone虚函数 for (auto* p : other.properties) { this->properties.push_back(p->clone()); } amountOfOwners++; // 拷贝构造时递增计数 } // 重载拷贝赋值运算符 Owner& Owner::operator=(const Owner& other) { if (this != &other) { // 先释放当前对象的properties内存 for (auto* p : this->properties) { delete p; } this->properties.clear(); // 拷贝成员变量 this->fullname = other.fullname; this->inn = other.inn; this->amountOfProperty = other.amountOfProperty; // 深拷贝properties for (auto* p : other.properties) { this->properties.push_back(p->clone()); } } return *this; } // 修改析构函数,释放properties内存 Owner::~Owner() { for (auto* p : properties) { delete p; } amountOfOwners--; }
注:需为Property类及其子类添加clone虚函数实现深拷贝,否则会引发指针悬挂和重复释放的未定义行为。
内容的提问来源于stack exchange,提问作者etmeow
相关产品推荐
相关产品推荐

