当然,答案是“不”,因为写它的人想了很多,但我想知道为什么。
考虑到(无模板)类通常在头文件中声明,然后包含在单独编译的几个文件中,请再考虑这两个文件:
文件1.c
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &foo) {
return sizeof(foo);
}
文件2.c
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize2(Foo const &foo) {
return sizeof(foo);
}
一般 Foo 会在头文件中声明并包含在两者中,但效果如上图。(也就是说,包含标题并不神奇,它只是将标题内容放在该行上。)我们可以编译两者并将它们链接到以下内容:
主文件
#include <iostream>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &);
size_t getsize2(Foo const &);
int main() {
Foo foo;
std::cout << getsize1(foo) << ", " << getsize2(foo) << ", " << sizeof(foo) << '\n';
}
一种方法是使用 g++:
g++ -std=c++11 -c -Wall file1.cc
g++ -std=c++11 -c -Wall file2.cc
g++ -std=c++11 -c -Wall main.cc
g++ -std=c++11 -Wall *.o -o main
并且(在我的架构和环境中),这显示:8、8、8。对于 file1.cc、file2.cc 和 main.cc 的每次编译,sizeof 都是相同的
但是 c++11 标准是否保证了这一点,期望与所有 3 Foo 的布局兼容真的可以吗?Foo 包含私有和公共字段,因此它不是 c++11 标准(工作草案)的 Clause 9 par 7 中定义的标准布局结构:
标准布局类是这样的类:
- 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
- 没有虚函数 (10.3) 和虚基类 (10.1),
- 对所有非静态数据成员具有相同的访问控制(第 11 条),
- 没有非标准布局的基类,
- 要么在派生最多的类中没有非静态数据成员,并且最多有一个具有非静态数据成员的基类,要么没有具有非静态数据成员的基类,并且
- 没有与第一个非静态数据成员相同类型的基类。
由于我们使用的是结构,并且为了彻底,下一个标准说:
标准布局结构是使用 class-key 结构或 class-key 类定义的标准布局类。标准布局联合是使用类键联合定义的标准布局类。
据我所知,该标准仅定义标准布局中结构之间的布局兼容性(第 9.2 条,第 18 条)。
如果两个标准布局结构(第 9 条)类型具有相同数量的非静态数据成员并且相应的非静态数据成员(按声明顺序)具有布局兼容类型(3.9),则它们是布局兼容的。
那么是否保证所有三个 Foo 都是布局兼容的,更重要的是为什么?
为什么在编译期间为 Foo 创建不同布局的(非确定性)编译器不是 c++11 编译器?