当前位置: 首页 > 知识库问答 >
问题:

析构函数必须对默认初始化的类成员仅可用(公共)或完全有效吗?

於宾白
2023-03-14

请考虑一个结构a具有U类型的字段U 并带有默认初始值设定项。析构函数~u 只声明:

template<typename T>
struct U {
    ~U();
};

struct R;

struct A {
    U<R> u = U<R>{};
};

所有编译器都接受此代码,demo:https://gcc.godbolt.org/z/oqmjtovmo

template<typename T>
struct U {
    ~U() { static_assert( sizeof(T) > 0 ); }
};

error: invalid application of 'sizeof' to an incomplete type 'R'

当然,这一探索不仅具有纯粹的理论意义。如果在这里将U替换为std::unique_ptr,那么就解释了为什么std::unique_ptr 类型的类字段被MSVC接受,而被gcc/clang拒绝用于不完整类r

共有1个答案

何聪
2023-03-14

[dcl.init.aggr]/8:(强调我的)

类类型的每个元素的析构函数都可能从发生聚合初始化的上下文中调用([class.dtor])。

[basic.def.odr]/8:

至于MSVC接受代码,它似乎是一个bug。

 类似资料:
  • 如果我有一个struct Foo和一个struct Bar: 如果我初始化一个条并打印正确得到的值: 但是现在如果我声明这样的构造函数: 我失去了Bar::foo的默认构造,程序输出了32764 0 5! 为什么我不得不像这样无声地初始化每个成员变量: 只要我声明一个构造函数?在这种情况下,为什么默认构造不起作用?

  • 问题内容: 为什么必须在构造函数完成之前初始化最终变量? 当我编译这段代码时,我得到这样的错误 err:变量q可能尚未初始化 问题答案: 官方理由是,它是由定义的Java语言规范8.3.1.2: 必须在声明该类的每个构造函数的末尾绝对分配一个空白的最终实例变量;否则会发生编译时错误。 空白的final是其声明缺少初始化程序(即您所描述的内容)的final变量。

  • 如果我有以下结构 我初始化为 这应该值初始化对象并根据标准执行以下操作: 如果T是一个(可能是cv限定的)类类型,没有用户提供或删除的默认构造函数,则该对象为零初始化,并检查默认初始化的语义约束,如果T有一个非平凡的默认构造函数,则该对象为默认初始化的; 有一个非常重要的构造函数,可以通过以下方法进行检查: 该标准是否意味着我的对象在值初始化的情况下应该始终为零初始化,然后随后默认初始化? 如果我

  • 编译良好:gcc Version4.8.5(Ubuntu4.8.5-2Ubuntu1~14.04.1) 结果出现错误:clang Version3.4-1Ubuntu3(TAGS/RELEASE_34/FINAL)(基于LLVM 3.4)

  • 是GCC和Clang中的bug,还是标准允许他们接受此代码?

  • 请帮我做这个程序: 这里,struct有一个私有析构函数,只是为了演示析构函数不是由编译器真正调用的,并简化代码的长度。 问题是: 如果不在此转换单元中编译,为什么要考虑字段默认初始化? 出现错误是因为为初始化字段创建了临时对象吗?(没有强制删除副本?) 那么和情况有什么不同?