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

C++自定义类含指针成员存入数组后访问崩溃的原因与解决方案

问题原因

你遇到的崩溃是野指针解引用触发的内存访问违规:

  • 当类成员是普通int类型时,未初始化的int存储的是栈上的随机垃圾值,直接读取虽然属于未定义行为,但通常不会触发内存访问异常,仅会得到错误的数值,所以程序可以正常退出。
  • 当类成员改为int*指针类型时,编译器生成的默认构造函数不会初始化该指针,指针会成为指向随机内存地址的野指针,调用getint()时执行*p解引用操作,相当于访问没有权限的非法内存地址,直接触发段错误,对应你看到的退出码3221225477(Windows平台下的访问违例退出码)。
可行实现方案

方案1:手动管理原生指针,遵守三五法则

如果你必须使用原生指针,需要主动实现构造函数初始化指针,同时补充析构、拷贝构造、拷贝赋值运算符(C++11及以上还可以补充移动构造、移动赋值),避免内存泄漏、重复释放、野指针问题:

#include <iostream>
class A
{
    int* p;
public:
    // 构造函数:初始化指针,分配内存
    A() : p(new int(0)) {}
    // 析构函数:释放内存
    ~A() { delete p; }
    // 拷贝构造:深拷贝
    A(const A& other) : p(new int(*other.p)) {}
    // 拷贝赋值:深拷贝
    A& operator=(const A& other) {
        if (this != &other) {
            *p = *other.p;
        }
        return *this;
    }

    void setint(int p_x);
    int getint();
};

void A::setint(int p_x) {*p = p_x;}
int A::getint() {return *p;}

int main()
{
    A arr_a[5];
    std::cout << arr_a[0].getint() << std::endl; // 输出初始值0
    arr_a[0].setint(10);
    std::cout << arr_a[0].getint() << std::endl; // 输出10
    return 0;
}

方案2:使用智能指针自动管理内存(更推荐)

C++11及以上版本可以用标准库的智能指针替代原生指针,不需要手动管理内存,也不需要手动实现析构、拷贝等特殊成员函数,编译器生成的默认函数即可满足需求:

#include <iostream>
#include <memory> // 智能指针头文件
class A
{
    std::unique_ptr<int> p;
public:
    // 构造函数初始化智能指针
    A() : p(std::make_unique<int>(0)) {}

    void setint(int p_x);
    int getint();
};

void A::setint(int p_x) {*p = p_x;}
int A::getint() {return *p;}

int main()
{
    A arr_a[5];
    std::cout << arr_a[0].getint() << std::endl;
    arr_a[0].setint(20);
    std::cout << arr_a[0].getint() << std::endl;
    return 0;
}

如果需要支持A实例的拷贝操作,可以将std::unique_ptr替换为std::shared_ptr。

方案3:指针指向外部已存在的合法int对象

如果指针不需要持有动态分配的内存,也可以让指针指向生命周期长于A实例的外部int对象,注意要避免指针悬空:

#include <iostream>
class A
{
    int* p;
public:
    // 构造函数传入外部int的地址
    explicit A(int* external_p) : p(external_p) {}

    void setint(int p_x);
    int getint();
};

void A::setint(int p_x) {*p = p_x;}
int A::getint() {return *p;}

int main()
{
    int val_arr[5] = {0}; // 外部int数组,生命周期和A数组一致
    A arr_a[5] = {A(&val_arr[0]), A(&val_arr[1]), A(&val_arr[2]), A(&val_arr[3]), A(&val_arr[4])};
    std::cout << arr_a[0].getint() << std::endl;
    arr_a[0].setint(30);
    std::cout << arr_a[0].getint() << std::endl;
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 20:15:06