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

包含带非平凡默认构造函数的glm::vec2的union引发构造报错

问题根因

  • 你的Foo结构体默认构造函数被隐式删除,核心原因是内部匿名联合体包含了非平凡默认构造的类型glm::vec2:C++标准规定,当联合体中存在没有用户提供默认构造函数的非平凡类型成员时,整个联合体的默认构造函数会被隐式删除,外层结构体Foo的默认构造函数因为依赖联合体的构造,也会跟着被删除。

解决方案1:显式指定联合体的激活成员(不需要placement new,最常用)

直接在Foo的构造函数里主动初始化你需要的联合体成员即可,比如你要默认用size的话,改写成:

struct Foo
{
    union
    {
        glm::vec2 size;
        struct { float width, height; };
    };

    // 显式初始化联合体的size成员,让构造函数合法
    Foo() : size(0.0f, 0.0f) {}
};

如果默认要激活的是width/height那个匿名结构体,就写成:

Foo() : width(0.0f), height(0.0f) {}

改完之后直接用new Foo就不会报错了。

解决方案2:使用placement new的实现方式

如果你确实有场景需要先分配内存、再晚一点初始化联合体成员,就可以用placement new,步骤如下:

  1. 先分配足够容纳Foo的裸内存,不调用构造函数
  2. 用placement new在已分配的内存上构造你需要激活的联合体成员

示例代码:

struct Foo
{
    union
    {
        glm::vec2 size;
        struct { float width, height; };
    };
    Foo() = default;
};

// 分配裸内存,大小和对齐要求匹配Foo
void* buf = operator new(sizeof(Foo));
Foo* foo = static_cast<Foo*>(buf);
// 用placement new显式构造glm::vec2成员,激活size分支
new (&foo->size) glm::vec2(1.0f, 2.0f); 

// 使用完之后手动析构激活的成员,再释放内存
foo->size.~vec2();
operator delete(buf);

注意:用placement new的场景下,你必须自己手动管理联合体的激活状态、析构对应的成员,不能直接调用delete foo,否则会出现未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 06:24:05