如何理解 C++17 标准参考中的 [intro.object]/3?
How is [intro.object]/3 in the C++17 Standard Reference to be understood?
N4659 的 [intro.object]/3(2017 年 3 月 post-Kona working draft/C++17 DIS)指出:
If a complete object is created ([expr.new]) in storage associated
with another object e of type “array of N unsigned char
” or of type
“array of N std::byte
” ([cstddef.syn]), that array provides storage
for the created object if:
(3.1) the lifetime of e has begun and not ended, and
(3.2) the storage for the new object fits entirely within e, and
(3.3) there is no smaller array object that satisfies these
constraints.
[ Note: If that portion of the array previously provided storage for
another object, the lifetime of that object ends because its storage
was reused ([basic.life]). — end note ]
[Example:
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)
— end example]
- 应该如何理解这段文字?
- 这如何解决并与数组的基本内容协调一致,例如sizeof(数组)?
- 除了指针,数组还提供了哪些完整的对象存储?
我会很感激能展示这里所说内容的插图,以便我能完全理解本文。
How does that work out and harmonize with the basic things about arrays e.g. sizeof(array)?
该段所说的内容与 sizeof
和数组的其他属性之间没有干扰。
Besides pointers, what other complete objects do arrays provide storage for?
看来您误解了示例。在示例中,几个对象是通过 placement new 在数组存储中创建的。和往常一样 new
return 是指向对象的指针,但数组中存储的是实际对象。
很难解释得更好,因为你的观点都是基于误解。无论如何,将示例的最后一部分稍作修改:
#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
的存储中创建了一个 B
(更具体地说,在 A
的 a
成员中)。在数组存储中放置一个对象对数组大小没有影响。放在数组存储中的是一个对象。 new
(和放置 new
)return 指向该对象的指针,可以取消引用以获取对实际对象的引用。
[intro.object]/3(2017 年 3 月 post-Kona working draft/C++17 DIS)指出:
If a complete object is created ([expr.new]) in storage associated with another object e of type “array of N
unsigned char
” or of type “array of Nstd::byte
” ([cstddef.syn]), that array provides storage for the created object if:(3.1) the lifetime of e has begun and not ended, and
(3.2) the storage for the new object fits entirely within e, and
(3.3) there is no smaller array object that satisfies these constraints.
[ Note: If that portion of the array previously provided storage for another object, the lifetime of that object ends because its storage was reused ([basic.life]). — end note ]
[Example:
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)
— end example]
- 应该如何理解这段文字?
- 这如何解决并与数组的基本内容协调一致,例如sizeof(数组)?
- 除了指针,数组还提供了哪些完整的对象存储?
我会很感激能展示这里所说内容的插图,以便我能完全理解本文。
How does that work out and harmonize with the basic things about arrays e.g. sizeof(array)?
该段所说的内容与 sizeof
和数组的其他属性之间没有干扰。
Besides pointers, what other complete objects do arrays provide storage for?
看来您误解了示例。在示例中,几个对象是通过 placement new 在数组存储中创建的。和往常一样 new
return 是指向对象的指针,但数组中存储的是实际对象。
很难解释得更好,因为你的观点都是基于误解。无论如何,将示例的最后一部分稍作修改:
#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
的存储中创建了一个 B
(更具体地说,在 A
的 a
成员中)。在数组存储中放置一个对象对数组大小没有影响。放在数组存储中的是一个对象。 new
(和放置 new
)return 指向该对象的指针,可以取消引用以获取对实际对象的引用。