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

如何延迟初始化类成员变量?C++构造器权限与实例声明问题

嘿,这个问题我之前也碰到过——就是想严格控制GlslProgram的构造方式,不让别人随便用默认构造器,但又得在BasicCubeExample里先声明成员变量,等格式明确了再初始化。给你几个靠谱的解决办法:

方案1:用std::optional延迟初始化(推荐C++17+)

这是最直观也最符合语义的方案,std::optional专门用来表示“可能存在也可能不存在”的对象,默认状态下不会构造内部的GlslProgram:

#include <optional>

class BasicCubeExample : public Application {
private:
    virtual void set_info() {
        Application::set_info();
        m_info.title = "Basic cube example";
    }

    // 初始为空,完全不调用GlslProgram的任何构造器
    std::optional<GlslProgram> m_shader;

    // 在合适的时机(比如初始化函数)再构造对象
    void init() override {
        GlslProgram::Format format;
        format.vertex("path/to/your/vertex.shader");
        // 调用目标构造器,直接在optional的内存里构造对象
        m_shader.emplace(format);
    }
};

这时候你就可以放心地把GlslProgram的默认构造器删除或者设为私有了:

class GlslProgram {
public:
    // ... 其他成员 ...
    // 删除默认构造器,禁止外部默认构造
    GlslProgram() = delete;
    GlslProgram(const Format& format, const bool separable = false);
    // ... 其他成员 ...
};
方案2:用智能指针(兼容C++11+)

如果你的项目还在用C++11/14,或者更习惯动态内存管理的方式,std::unique_ptr也是个稳妥的选择:

#include <memory>

class BasicCubeExample : public Application {
private:
    virtual void set_info() {
        Application::set_info();
        m_info.title = "Basic cube example";
    }

    // 初始为nullptr,不构造GlslProgram对象
    std::unique_ptr<GlslProgram> m_shader;

    void init() override {
        GlslProgram::Format format;
        format.vertex("path/to/your/vertex.shader");
        // 动态构造对象,调用目标构造器
        m_shader = std::make_unique<GlslProgram>(format);
    }
};

智能指针会自动管理内存,不用手动delete,同样可以删除GlslProgram的默认构造器,因为这里只是声明了指针,并没有构造GlslProgram实例。

方案3:手动内存管理(进阶场景)

如果对内存布局有严格要求(比如不想用动态分配),可以用std::aligned_storage预留内存,之后手动构造和析构对象:

#include <type_traits>

class BasicCubeExample : public Application {
private:
    virtual void set_info() {
        Application::set_info();
        m_info.title = "Basic cube example";
    }

    // 预留足够容纳GlslProgram的内存,并保证对齐
    typename std::aligned_storage<sizeof(GlslProgram), alignof(GlslProgram)>::type m_shader_storage;
    GlslProgram* m_shader = nullptr;

    void init() override {
        GlslProgram::Format format;
        format.vertex("path/to/your/vertex.shader");
        // 手动在预留内存上构造对象(placement new)
        m_shader = new (&m_shader_storage) GlslProgram(format);
    }

    // 必须手动调用析构函数清理
    ~BasicCubeExample() override {
        if (m_shader != nullptr) {
            m_shader->~GlslProgram();
        }
    }
};

这个方案完全控制对象的生命周期,但代码复杂度高,容易出错,只推荐在对性能或内存布局有特殊要求的场景使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:23:39