Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 执行C++;标准保证未使用的私有字段将影响sizeof?_C++_Sizeof_Language Lawyer - Fatal编程技术网

C++ 执行C++;标准保证未使用的私有字段将影响sizeof?

C++ 执行C++;标准保证未使用的私有字段将影响sizeof?,c++,sizeof,language-lawyer,C++,Sizeof,Language Lawyer,考虑以下结构: class Foo { int a; }; 在g++中测试时,我得到sizeof(Foo)==4,但这是标准保证的吗?是否允许编译器注意到a是一个未使用的私有字段,并将其从类的内存表示中删除(导致较小的sizeof) 我不希望任何编译器能进行这种优化,但这个问题突然出现在一个语言法律讨论中,所以我现在很好奇。 < P> C++标准并没有定义很多关于内存布局的问题。这种情况下的基本规则是第9节中的第4项: 4类类型的完整对象和成员子对象应具有非零大小。[注:类对象可以赋值

考虑以下结构:

class Foo {
    int a;
};
在g++中测试时,我得到
sizeof(Foo)==4
,但这是标准保证的吗?是否允许编译器注意到
a
是一个未使用的私有字段,并将其从类的内存表示中删除(导致较小的sizeof)


我不希望任何编译器能进行这种优化,但这个问题突然出现在一个语言法律讨论中,所以我现在很好奇。

< P> C++标准并没有定义很多关于内存布局的问题。这种情况下的基本规则是第9节中的第4项:

4类类型的完整对象和成员子对象应具有非零大小。[注:类对象可以赋值,作为参数传递给函数,并由函数返回(复制或移动受到限制的类对象除外;参见12.8)。其他合理的运算符,如相等比较,可由用户定义;参见13.5.-结束注释]

不过,现在还有一个限制:标准布局类。(没有静态元素,没有虚拟元素,所有成员的可见性都相同)第9.2节“类成员”要求标准布局类的不同类之间具有布局兼容性。这样可以防止从此类类中删除成员


对于非普通的非标准布局类,我看不到标准中有进一步的限制。sizeof()、reinterpret_cast()、的确切行为。。。是实现定义的(即5.2.10“映射函数是实现定义的”)。

如果您查看模板,您会注意到,这样的“优化”通常在输出中几乎没有任何内容,即使模板文件可能有数千行


我认为您所说的优化几乎总是发生在一个函数中,当对象在堆栈上使用时,对象不会被复制或传递到另一个函数,并且私有字段从未被访问(甚至没有初始化……这可能被视为一个bug!)

答案是肯定和否定。编译器不能在标准中准确地表现出这种行为,但它可以部分地表现出来

如果结构的存储从未被引用,那么编译器没有理由不能优化该存储。如果编译器的分析正确,那么您编写的任何程序都无法判断存储是否存在

但是,编译器无法报告更小的sizeof()。该标准非常明确,对象必须足够大,以容纳其包含的位和字节(例如,参见N3797中的3.9/4),并且报告小于容纳int所需大小的sizeof是错误的

在N3797 5.3.2中:

sizeof运算符生成对象中的字节数 其操作数的表示

我不认为“表示”可以根据引用的是结构还是成员而改变

从另一个角度来看:

struct A {
  int i;
};
struct B {
  int i;
};
A a;
a.i = 0;
assert(sizeof(A)==sizeof(B));

我不认为在符合标准的实现中可以允许此断言失败。

在这种情况下,肯定不会失败:它是一个标准布局类,因此可以通过
reinterpret\u cast
访问成员。(我不确定对于更复杂的类是否会被禁止)。我想编译器很快就很难验证成员是否未被使用(间接通过指针魔术或其他翻译单元等)在许多编译器中,您可以运行代码分析,对未使用的字段发出警告。我相信根据“好像”优化规则,编译器当然可以删除字段,但前提是它的操作方式与未删除字段的操作方式相同。因此,如果使用sizeof,则无法删除该字段。虽然没有标准参考,所以不是官方答案。顺便说一下,我已经看到了我在阅读编译代码反汇编时提到的效果。函数堆栈上的一个结构消失在寄存器中,根本没有内存位置。第一句话只是说大小不能是
0
,所以它没有意义。可能是1。我也不明白9.2是如何禁止不使用元素的删除的-1尺寸非0报价是相关的,因为这是标准对尺寸提出任何要求的少数情况之一。从9.2我读到它必须与另一个类兼容。另一个类可能使用该元素,因此无法删除该元素。如果在其中一个元素中删除了它,但在另一个元素中没有删除,那么它们是不兼容的。但我当然不会声称掌握了标准。间接访问元素仍然意味着访问它。因此,无论如何,在这种情况下都无法执行优化。这就是为什么这个论点毫无意义。标准对sizeof施加了许多限制。看看我的答案吧。