Aggregate class and POD
http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176
An aggregate is an array or a class (clause 9) with no user-declared constructors (12.1), no private or protected non-static data members (clause 11), no base classes (clause 10), and no virtual functions (10.3).
Now let's see how aggregates are special. They, unlike non-aggregate classes, can be initialized with curly braces {}
. This initialization syntax is commonly known for arrays, and we just learnt that these are aggregates
POD
An aggregate class is called a POD if it has no user-defined copy-assignment operator and destructor and none of its nonstatic members is a non-POD class, array of non-POD, or a reference.
Initialize struct to 0
两种 http://stackoverflow.com/questions/1998752/memset-or-value-initialization-to-zero-out-a-struct
1.
STRUCT theStruct;
memset( &theStruct, 0, sizeof( STRUCT ) );
or
2.STRUCT theStruct ={};
具体的例子
struct POD_OnlyStruct
{
int a;
char b;
};
POD_OnlyStruct t = {}; // OK
POD_OnlyStruct t;
memset(&t, 0, sizeof t); // OK as well
In this case writing a POD_OnlyStruct t = {}
or POD_OnlyStruct t; memset(&t, 0, sizeof t)
doesn't make much difference, as the only difference we have here is the alignment bytes being set to zero-value in case of memset
used. Since you don't have access to those bytes normally, there's no difference for you.
On the other hand, since you've tagged your question as C++, let's try another example, with member types different from POD:
struct TestStruct
{
int a;
std::string b;
};
TestStruct t = {}; // OK
{
TestStruct t1;
memset(&t1, 0, sizeof t1); // ruins member 'b' of our struct
} // Application crashes here
In this case using an expression like TestStruct t = {}
is good, and using a memset
on it will lead to crash. Here's what happens if you use memset
- an object of type TestStruct
is created, thus creating an object of type std::string
, since it's a member of our structure. Next, memset
sets the memory where the object b
was located to certain value, say zero. Now, once our TestStruct object goes out of scope, it is going to be destroyed and when the turn comes to it's member std::string b
you'll see a crash, as all of that object's internal structures were ruined by the memset
.
链接:https://www.zhihu.com/question/36379130/answer/69853366
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
- 首先是平凡的(trival)定义,通常一个平凡的类或者结构体需要满足以下定义:
- 拥有平凡的默认构造函数和析构函数。默认的意思就是由编译器为我们自动生成的,不许是我们自己定义的,但是由于c++11提供了default,也可以是自己定义的加=default,比如
Trival(){}=default;
}
就是满足这个要求的,而
struct noTrival{
noTrival(){};
}
就不满足这个要求(哪怕我们定义的构造函数体里面啥都没有)。 这个要求对于带参的构造函数没有束缚。你可以自定义带参的构造函数。只要不是默认的就好
- 拥有平凡的拷贝构造函数和移动构造函数。默认的意思同上,也可以使用=default。
- 拥有平凡的拷贝赋值操作符和移动赋值操作符。
- 不能包含虚函数和虚基类。
2.接下来是标准布局的定义: standard layout
- 所有非静态成员拥有相同的访问级别,(访问级别就是public,private,protected),
private :
int a;
public:
int b;
} 就不满足标准布局,因为a,b访问级别不同 。
- 在类和结构体继承时需要满足以下两个情况之一:
- 派生类中有非静态类,那么这个派生类只能有且只有一个仅包含了静态成员的基类。
- 基类有非静态成员,那么派生类中不允许有非静态成员。
- 类中第一个非静态类型与基类不是同一个类型。比如
B b;
int c;
}就不符合这个条件。因为A中第一个成员是基类B类型的。
- 没有虚类和虚基类(与trival中重复)
- 所有非静态数据成员都符合标准布局的要求,这其实就是一个递归的定义。
说了这么多,那么为什么我们需要POD这种条件满足的数据呢?
- 可以使用字节赋值,比如memset,memcpy操作
- 对C内存布局兼容。
- 保证了静态初始化的安全有效。
Don't use malloc in C++ (unless you absolutely know what youre doing)
https://stackoverflow.com/questions/30579430/access-violation-writing-location-0xcdcdcdcd
ptrStack stack = (ptrStack)malloc(sizeof(Stack));
The Stack
structure contains an object of type string
. The string
constructor must be called before you can use the string
. If you allocate memory using the C++ new
operator, then the constructor is automatically called, and the string
is properly initialized.
But if you allocate memory using the C malloc
function, then the string
constructor is not called. The 0xCDCDCDCD
comes from an uninitialized pointer in the string object that should have been initialized by the constructor (but wasn't because the constructor was not called).