gpt4 book ai didi

c++ - 为什么内联用户提供的构造函数 odr 使用基类构造函数?

转载 作者:行者123 更新时间:2023-12-03 23:41:01 25 4
gpt4 key购买 nike

考虑以下说明性示例

#include <iostream>

template <typename>
struct Base {
static int const touch;
Base() {
(void)touch;
}
};

template<typename CRTP>
int const Base<CRTP>::touch = []{
std::cout << "Initialized!\n";
return 0;
}();

struct A : Base<A> {
A() {}
};

struct B : Base<B> {
B() = default;
};

int main() {
}
当上述程序由 GCC编译时, ClangVC++并执行后,始终会看到以下输出:
Initialized!
所有三个编译器都发出 Base<A>::touch 的定义和初始化,而两者都不发出 Base<B>::touch 的定义和初始化(也通过 Godbolt 验证)。所以我会得出结论,这是标准的受制裁行为。
对于 B 的默认构造函数, 我们有

[class.ctor]

7 A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used to create an object of its class type ([intro.object]) or when it is explicitly defaulted after its first declaration.


从中可以得出结论,因为这两个条件都不适用于我们的 TU, B::B()永远不会被隐式定义。所以它从不使用 ODR Base<B>::Base()Base<B>::touch .我觉得这很合理。
但是,我不明白为什么 A::A()最终 odr 使用其基类的成员。我们知道

[class.mfct]

1 A member function may be defined in its class definition, in which case it is an inline member function ...

[dcl.inline]

6 An inline function or variable shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case ([basic.def.odr]).

[basic.def.odr]

4 ... A constructor for a class is odr-used as specified in [dcl.init].


我们从不初始化任何 A 类型的对象,所以我们不应该使用它的构造函数。所以我们的程序最终不会包含 A::A() 的任何定义。 .
那么为什么它表现得好像定义存在一样?为什么 odr-use Base<A>::Base()并导致其实例化?

最佳答案

对于 odr-use Base<T>::Base 的任何内联定义都会发生这种情况, 例如:

inline void x() {
Base<char>();
}

struct A : Base<A> {
A(int) {}
void x() {
Base<int>();
}
};

struct C : Base<C> {
C();
};

inline C::C() = default; // See [1]

// Will print "Initialized!" four times
B() = default不使用 ODR Base<T>::Base因为它只定义为 defaulted .即使在结构上是根据 [basic.def]/2 的定义,由于 [class.ctor]/7 (如您所引用的),它不会“发出”。 odr 使用的定义 Base<T>::Base仅在 B::B() 时(隐式)定义本身就是 odr 使用的。
对于定义的其他内联函数,不存在此类豁免。它们的定义无条件(和结构上)包含 odr-use Base<T>::Base . A::A()在您的示例中是一个定义,并且您的程序确实包含 A::A() 的定义使用 Base<T>::Base .
“内联函数或变量应在每个使用 odr 的翻译单元中定义”。这是一个“应”要求(对于每个使用 odr 内联函数的 TU,都需要定义),而不是 odr 使用内联函数的结果。

[1] 由于 [dcl.fct.def.default]/5 :

A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted


所以 C::C()有一个默认定义,它立即生成“隐式”定义。

关于c++ - 为什么内联用户提供的构造函数 odr 使用基类构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65861630/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com