我看到一些奇怪的行为,我在这个结构内联初始化的后期向量中描述.支撑-初始化列表
我希望消除一个未定义行为的可能来源.我有以下两个类A,B它们都转发声明,struct Foo但cpp文件定义了如下的实际结构.
// This is A.h
namespace app {
struct Foo;
class A {
private:
std::vector<Foo> fooList;
};
}
// This is A.cpp
struct app::Foo {
std::string first;
std::string second;
unsigned flag;
};
// This is B.h
namespace app {
struct Foo;
class B {
private:
std::vector<Foo> fooList;
};
}
// This is B.cpp
struct app::Foo {
std::string first;
std::string second;
bool flag;
float value;
};
Run Code Online (Sandbox Code Playgroud)
请注意,结构Foo在cpp文件中具有不同的成员A.cpp,B.cpp.这些类A和B从未暴露成员fooList.是否有可能由于前向声明完全相同,在文件A.h和B.h结构中Foo,生成的代码可能正在使用其中一个.这可以解释我在链接问题中看到的问题.
换句话说,虽然对于Foo调用的结构使用了braced-init-list,但是B.cpp它是否可以保证使用Foo定义的内容,B.cpp或者同样可能使用Foo定义的内容A.cpp?
即使在我写这篇文章时,我立即意识到这种实现是一种不好的做法,因为Foo它本身就是类的内部A,B并且应该真正在类本身的私有部分中声明.
这违反了ODR(一个定义规则).
该计划格式错误,无需诊断.
如果你这样做,那么C++标准绝对允许任何行为.它可以"工作",它可以选择一个并丢弃另一个,它可以工作,直到你重新链接,它可以格式化你的硬盘.
我在一个真实的现场项目中做到了这一点; 我们有一个矩阵标题,您可以在包含它之前定义标记,如果它支持float或double.
这"工作",而我们从未在同一个DLL中使用这两个版本.然后我们使用了两个版本.
编译器将根据一组巧合为结构选择一种尺寸或另一种尺寸,并根据略微不同的一组巧合选择一个构造函数或其他构造函数.我们的内存腐败很多.但有时只在某些版本上.
我们通过将代码包装在名称中包含标量类型的命名空间中来快速"修复"它,然后using将它们带入外部命名空间.
| 归档时间: |
|
| 查看次数: |
150 次 |
| 最近记录: |