Non-static data members
非静态数据成员
非静态数据成员在成员规格一堂课。
二次
class S
{
int n; // non-static data member
int& r; // non-static data member of reference type
int a[10] = {1, 2}; // non-static data member with initializer (C++11)
std::string s, *ps; // two non-static data members
struct NestedS {
std::string s;
} d5, *d6; // two non-static data members of nested type
char bit : 2; // two-bit bitfield
};
二次
任何简单声明是允许的,除了。
extern
和register
不允许存储类说明符;
thread_local
不允许存储类说明符%28,但允许静态数据成员%29;
- 不完全类型是不允许的:特别是,一个类。
C
不能具有类型的非静态数据成员。C
,尽管它可以具有类型为非静态的数据成员。C&
%28提及C
%29或C*
%28指针到C
%29;
- 如果至少存在一个用户声明的构造函数,则非静态数据成员不能具有与类名称相同的名称;
- 大自动说明符不能在非静态数据成员声明%28中使用,尽管它允许用于下列静态数据成员:在类定义中初始化29%。
此外,位字段声明是允许的。
布局
当某个类的对象C
,则非引用类型的每个非静态数据成员将在C
引用成员是否占用任何存储空间是实现定义的,但它们的存储时间与其成员所在的对象相同。
对于非-联合类类型,成员具有相同的成员访问总是被分配,以便以后声明的成员在类对象中具有更高的地址。具有不同访问控制的成员按%28的未指定顺序分配,编译器可以将它们分组到%29。对齐要求可能需要在成员之间或类的最后一个成员之后填充。
标准布局
所有非静态数据成员都具有相同的访问控制且满足某些其他条件的类称为标准布局类型
28%见StandardLayoutType
有关要求列表%29。
两个标准布局的非联合类类型可能具有公共初始序列
对于非静态数据成员和自C++14%29以来的位字段%28,对于一个或多个初始成员序列(按声明%29的顺序排列),如果成员具有与布局兼容的类型,如果它们是位字段,则它们具有相同的宽度%28自C++14%29。
二次
struct A { int a; char b; };
struct B { const int b1; volatile char b2; };
// A and B's common initial sequence is A.a, A.b and B.b1, B.b2
struct C { int c; unsigned : 0; char b; };
// A and C's common initial sequence is A.a and C.c
struct D { int d; char b : 4; };
// A and D's common initial sequence is A.a and D.d
struct E { unsigned int e; char b; };
// A and E's common initial sequence is empty
二次
两种标准布局不合并类类型称为布局兼容
如果它们是相同的类型,忽略cv-限定符,如果有自C++14%29以来的%28,则布局兼容
。枚举,或者如果他们公共初始序列
由每个非静态数据成员和位字段%28组成,因为在上面的示例中,C++14%29%28,A
和B
布局兼容
%29。
两个标准布局联合被称为布局兼容
如果它们具有相同数量的非静态数据成员和相应的非静态数据成员%28,则%29具有与布局兼容
的类型。
标准布局类型具有以下特殊属性:
If a standard-layout union holds two (or more) standard-layout structs as members, and these structs have a common initial sequence of data members, it is well-defined to examine any member of that common initial sequence regardless of which member of the union is active. | (until C++14) |
---|---|
In a standard-layout union with an active member of non-union class type T1, it is permitted to read a non-static data member m of another union member of non-union class type T2 provided m is part of the common initial sequence of T1 and T2 (except that reading a volatile member through non-volatile glvalue is undefined). | (since C++14) |
- 如果标准布局联合持有两个%28或更多%29的标准布局结构作为成员,并且这些结构具有数据成员的公共初始序列,因此无论哪个联合成员处于活动状态,检查该公共初始序列的任何成员都是定义良好的。%28直到C++14%29
- 在具有非联合类类型的活动成员的标准布局联合中。
T1
,则允许读取非静态数据成员。m
非工会类类型的其他工会成员的T2
提供m
的公共初始序列的一部分。T1
和T2
%28除外,通过非易失性极值读取易失性成员是未定义的%29。
%28自C++14%29
- 指向标准布局结构类型的对象的指针可以是重释[医]铸造指向其第一个非静态数据成员%28的指针(如果它有非静态数据成员%29),或者如果它有%29,则指向它的第一个基类次对象%28,反之亦然。%28填充在第一个数据成员%29之前是不允许的。请注意严格混叠规则仍然适用于这类投票的结果。
- 宏
offsetof
可用于从标准布局结构开始时确定任何成员的偏移量。
成员初始化
非静态数据成员可以通过以下两种方式之一初始化:
1%29成员初始化列表构造函数的。
二次
struct S
{
int n;
std::string s;
S() : n(7) // direct-initializes n, default-initializes s
{ }
};
二次
2) Through a default member initializer, which is simply a brace or equals initializer included in the member declaration, which is used if the member is omitted in the member initializer list struct S { int n = 7; std::string s{'a', 'b', 'c'}; S() // copy-initializes n, list-initializes s { } }; If a member has a default member initializer and also appears in the member initialization list in a constructor, the default member initializer is ignored. #include | (since C++11) |
---|---|
Reference members cannot be bound to temporaries in a default member initializer (note; same rule exists for member initializer lists). struct A { A() = default; // OK A(int v) : v(v) { } // OK const int& v = 42; // OK }; A a1; // error: ill-formed binding of temporary to reference A a2(1 // OK (default member initializer ignored because v appears in a constructor) // however a2.v is a dangling reference Reference members cannot be initialized with a default member initializer if it has a subexpression that would execute aggregate initialization which would use the same initializer: struct A; extern A a; struct A { const A& a1{ A{a, a} }; // OK const A& a2{ A{} }; // error }; A a{a, a}; // OK | (since C++14) |
使用
非静态数据成员或非静态成员函数的名称只能在以下三种情况下出现:
1%29作为类成员访问表达式的一部分,其中类要么具有此成员,要么来自具有该成员的类,包括隐式的this->在以下任何上下文中使用非静态成员名称时出现的成员访问表达式:这允许在成员函数体内的%28,在成员初始化程序列表中,在类内默认成员初始化器%29中。
二次
struct S
{
int m;
int n;
int x = m; // OK: implicit this-> allowed in default initializers (C++11)
S(int i) : m(i), n(m) // OK: implicit this-> allowed in member initializer lists
{
this->f( // explicit member access expression
f( // implicit this-> allowed in member function bodies
}
void f(
};
二次
2%29组成a指向非静态成员的指针...
二次
struct S
{
int m;
void f(
};
int S::*p = &S::m; // OK: use of m to make a pointer to member
void (S::*fp)() = &S::f; // OK: use of f to make a pointer to member
二次
3) (for data members only, not member functions) When used in unevaluated operands. struct S { int m; static const std::size_t sz = sizeof m; // OK: m in unevaluated operand }; std::size_t j = sizeof(S::m + 42 // OK: even though there is no "this" object for m | (since C++03) |
---|
缺陷报告
以下行为更改缺陷报告追溯应用于先前发布的C++标准。
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 613 | C++03 | unevaluated uses of non-static data members not allowed | such uses are allowed |
CWG 1696 | C++14 | reference members could be initialized to temporaries (whose lifetime would end at the end of ctor) | such init is ill-formed |
CWG 1397 | C++11 | class was regarded as complete in the default member initializers | default member init cannot trigger definition of default ctor |
CWG 1719 | C++14 | differently cv-qualified types weren't layout-compatible | cv-quals ignored, spec improved |
另见
- 班
- 静态数据成员
- 成员函数
std::is_standard_layout
offsetof
© cppreference.com
在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。