C++ 内联构造函数和一个定义规则

C++ 内联构造函数和一个定义规则,c++,one-definition-rule,C++,One Definition Rule,考虑以下源文件 1.cpp #包括 使用名称空间std; 结构X { X() { cout这确实违反了ODR(3.2)-特别是一个内联函数可以有多个定义,但这些定义必须相同(3.2/5)-并导致未定义的行为,因此任何情况都可能发生,编译器/链接器不需要对此进行诊断。您看到该行为的最可能原因是函数调用是内联的,并且不参与链接,因此不会发出链接错误。如果内联函数(例如您的类构造函数)在不同的转换单元中有不同的定义。ODR不适用于内联函数。@Kerrek SB:内联函数的行为描述是ODR描述的延续。我

考虑以下源文件 1.cpp

#包括
使用名称空间std;
结构X
{
X()
{

cout这确实违反了ODR(3.2)-特别是一个内联函数可以有多个定义,但这些定义必须相同(3.2/5)-并导致未定义的行为,因此任何情况都可能发生,编译器/链接器不需要对此进行诊断。您看到该行为的最可能原因是函数调用是内联的,并且不参与链接,因此不会发出链接错误。

如果内联函数(例如您的类构造函数)在不同的转换单元中有不同的定义。

ODR不适用于内联函数。@Kerrek SB:内联函数的行为描述是ODR描述的延续。我试图将编译单元编译为对象文件,然后将它们以两个顺序链接。结果不同,所以它会在我看来是链接器“扔掉”附加定义。@Dmitriy Matveev:这是允许的。事实上,当行为未定义时,任何东西都是允许的。为什么是UB?两个翻译单元看到的是不同的
X::X
;我同意两者都在同一全局范围内。但这样会出什么问题呢?@iammilind:因为
X::X
是内联的,所以
X的所有定义都是内联的::X
在整个程序中必须是完全相同的,否则行为是未定义的。这是3.2/5的要求。如果我将
[[gnu::noinline]]
用于clang3.6.1,则输出为1,而不考虑为编译器和链接器指定的文件名顺序。
#include <iostream>

using namespace std;

struct X
{
    X()
    {
        cout << "1" << endl;
    }
};

void bar();

void foo()
{
    X x;
}

int main()
{
    foo();
    bar();
    return 0;
}
#include <cstdio>

struct X
{
    X()
    {
        printf("2\n");
    }
};

void bar()
{
    X x;
}