如何正确初始化含两个指针成员的C++类?直接实例化崩溃如何解决
问题根因与修复方案
所有崩溃和异常本质是野指针访问,你的代码存在以下核心错误:
- 默认构造函数变量遮蔽(最直接原因):你在默认构造函数内部重新定义了和类成员同名的局部变量
p_real、p_imaginar,堆内存分配给了局部变量,类本身的成员指针全程未初始化,是野指针。直接调用operator<<或getter时访问野指针指向的内存,直接触发崩溃。调用setter后类成员指针被赋值为有效地址,因此暂时不会崩溃。 - 拷贝构造逻辑错误:拷贝构造函数执行时,类成员
p_real、p_imaginar还未初始化,直接判断if (p_real != nullptr)完全无效,野指针判断结果不可预期,后续操作大概率触发内存错误。 - 内存释放逻辑全错:析构函数、setter函数中都先执行
p_real = nullptr再调用delete p_real,等于直接丢失原内存地址,既没有释放原有堆内存造成泄漏,delete空指针也完全没有实际作用。 - 运算符重载语法错误:你已经把
operator<<声明为友元全局函数,后续实现却写为类成员函数,语法不合法,编译阶段本就应该报错。 - 对象声明语法错误:你的类名是
numar_complex,声明对象时写的numar complex x多了空格,属于语法错误。
修正后的完整代码
#include <iostream> class numar_complex { friend std::ostream& operator<<(std::ostream& out, const numar_complex& num); friend std::istream& operator>>(std::istream& is, numar_complex& num); private: double* p_real; double* p_imaginar; public: // 构造、析构 numar_complex() { // 直接给类成员指针赋值,不要重新定义局部变量 p_real = new double(0.0); p_imaginar = new double(0.0); std::cout << "constructor" << std::endl; } numar_complex(const numar_complex& nr) { // 拷贝构造不需要先释放,当前对象成员还未初始化,直接分配新内存即可 p_real = new double(*nr.p_real); p_imaginar = new double(*nr.p_imaginar); std::cout << "copy constructor " << std::endl; } ~numar_complex() { // 先释放内存,再置空指针 delete p_real; p_real = nullptr; delete p_imaginar; p_imaginar = nullptr; std::cout << "destructor" << std::endl; } // getter double get_p_real() const { return *p_real; } double get_p_imaginar() const { return *p_imaginar; } // setter void set_p_real(double x) { // 先释放原有内存,再分配新内存 delete p_real; p_real = new double(x); } void set_p_imaginar(double x) { delete p_imaginar; p_imaginar = new double(x); } }; // 友元运算符重载要放在类外面实现 std::ostream& operator<<(std::ostream& out, const numar_complex& num) { if (*num.p_imaginar >= 0) { out << *num.p_real << "+" << *num.p_imaginar << "*i \n"; } else { out << *num.p_real << *num.p_imaginar << "*i \n"; } return out; }
正确调用示例
int main() { numar_complex x; std::cout << x; // 输出0+0*i,不会崩溃 x.set_p_real(1); x.set_p_imaginar(1); std::cout << x; // 输出1+1*i return 0; }
内容的提问来源于stack exchange,提问作者Dragos Polifronie
相关产品推荐
相关产品推荐

