N4659号文件[Intro.Object]/3(2017年3月Kona后工作草案/C++17 DIS)规定:
如果在与类型为“array of Nunsigned char
”或类型为“array of Nstd::byte
”([CSTDDEF.SYN])的另一个对象e关联的存储中创建了一个完整的对象([Expr.New]),则该数组为创建的对象提供存储,如果:
(3.1)e的寿命已开始但未结束,并且
(3.2)新对象的存储完全适合e,并且
(3.3)没有更小的数组对象满足这些约束条件。
[注意:如果数组的那个部分以前为另一个对象提供了存储空间,则该对象的生存期将结束,因为它的存储空间被重用([basic.life])。-结束注意]
[示例:
template<typename ...T>
struct AlignedUnion {
alignas(T...) unsigned char data[max(sizeof(T)...)];
};
int f() {
AlignedUnion<int, char> au;
int *p = new (au.data) int; // OK, au.data provides storage
char *c = new (au.data) char(); // OK, ends lifetime of *p
char *d = new (au.data + 1) char();
return *c + *d; // OK
}
struct A { unsigned char a[32]; };
struct B { unsigned char b[16]; };
A a;
B *b = new (a.a + 8) B; // a.a provides storage for *b
int *p = new (b->b + 4) int; // b->b provides storage for *p
// a.a does not provide storage for *p (directly),
// but *p is nested within a (see below)
-结束示例]
我将感谢插图,将演示什么说在这里,使我可以完全理解这段文字。
它是如何与数组的基本内容(如sizeof(array))协调一致的呢?
该段的内容与sizeof
和数组的其他属性之间没有任何干扰。
除了指针,数组还为哪些完整的对象提供存储?
看来你误解了这些例子。 在这些示例中,几个对象通过placement New在数组存储中创建。 通常,new
返回指向对象的指针,但存储在数组中的是实际对象。
很难解释清楚,因为你们的观点都是基于一个误解。 无论如何,对示例的最后一部分稍作修改:
#include <iostream>
struct A { unsigned char a[32]; };
struct B {
unsigned char b[16];
void hello_world() {
std::cout << "hello world";
}
};
int main() {
A a;
B *b = new (a.a + 8) B; // a.a provides storage for *b
std::cout << sizeof(a.a) << "\n";
std::cout << sizeof(b->b) << "\n";
B& bref = *b;
bref.hello_world();
}
这里,在a
的存储中(更具体地说,在a
的a
成员中)创建了b
。 在数组存储中放置对象对数组大小没有影响。 放置在数组存储中的是一个对象。 new
(和放置new
)返回指向该对象的指针,可以取消引用该指针以获取对实际对象的引用。