【发布时间】:2017-02-09 01:10:18
【问题描述】:
#include <iostream>
#include <cstring>
// This struct is not guaranteed to occupy contiguous storage
// in the sense of the C++ Object model (§1.8.5):
struct separated {
int i;
separated(int a, int b){i=a; i2=b;}
~separated(){i=i2=-1;} // nontrivial destructor --> not trivially copyable
private: int i2; // different access control --> not standard layout
};
int main() {
static_assert(not std::is_standard_layout<separated>::value,"sl");
static_assert(not std::is_trivial<separated>::value,"tr");
separated a[2]={{1,2},{3,4}};
std::memset(&a[0],0,sizeof(a[0]));
std::cout<<a[1].i;
// No guarantee that the previous line outputs 3.
}
// compiled with Debian clang version 3.5.0-10, C++14-standard
// (outputs 3)
削弱标准保证以致该程序可能表现出未定义行为的原因是什么?
标准说: “数组类型的对象包含一个连续分配的非空集合,由 N 个类型为 T 的子对象组成。” [dcl.array] §8.3.4。 如果类型 T 的对象不占用连续的存储空间,那么这些对象的数组怎么办?
编辑:删除可能分散注意力的说明文字
【问题讨论】:
-
什么意思是对象不占用连续存储?您是在谈论可能在成员变量之间的填充吗?
-
对于您的第一个问题:因为没有人愿意围绕
memset这样的 C 东西设计 C++。 C 结构体需要与memset兼容以实现兼容性,其余的并不重要。 -
这是哪里来的?你有没有运行它并没有得到3?有一条评论说“不保证......”但我不知道是谁在断言。
-
@JoachimPileborg 该标准允许实现对象所需的部分存储在完全独立的内存区域(例如 vtables)中
-
除了对象不连续之外,还有很多很好的理由为什么
memsetting 一个“复杂”对象应该是 UB。
标签: c++ arrays c++14 language-lawyer memory-layout