c – 一个定义规则警告

前端之家收集整理的这篇文章主要介绍了c – 一个定义规则警告前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我被一个令人讨厌的“一个定义规则”违规所困扰.
我现在害怕在我的项目中有很多微妙的错误.

例如,以下程序将导致使用visual studio 2015的空指针取消引用:

Source1.cpp:
----------
struct S {
    double d = 0;
};

void Foo() {
    S s;
}


Source2.cpp:
-----------
struct S {
    int a = 0;
};

int main() {

    int value = 5;
    int& valueRef = value;
    S s;           // valueRef is erased due to S::d initialization from Source1.cpp

    valueRef++;    // crash
}

编译时没有任何警告.

这很糟糕,因为Source2.cpp甚至不使用Source1.cpp中的任何东西.如果我从项目中删除Source1.cpp,它仍然编译,并且不再有问题.

在大型项目中,似乎很难确保没有cpp文件“本地”定义具有已定义名称的结构或类.

我有一些类,如Point,Serie,State,Item,……我虽然这在小cpp文件中没问题,但我发现它不安全.

是否有编译器警告来捕获此类错误
如果没有,避免ODR违规的最佳做法是什么?

解决方法

在这种特殊情况下,在最底部,ODR违规(实际上导致您正在观察的问题)是类S的隐式定义的内联构造函数.您的程序有两个不匹配的内联S :: S()版本函数,可以看作是由原始ODR违规引起的另一个ODR违规(即同一类定义不同).

在C编译基础结构的当前方法中,实现很难“看到”此错误.当然,可以做足够的努力.

在这种情况下,为了使错误“可见”,您可以显式声明并将类构造函数定义为具有空主体的非内联函数.存在两个非内联S :: S()将触发链接错误.

可以理解的是,您可能会认为这是一种过于人为的措施,在某些情况下是不可接受的,因为它可能会改变班级的“聚合”状态.

猜你在找的C&C++相关文章