C++ Aggregate 与 POD(Plain Old Data)的解释

无论是 Aggregate 还是 POD(Aggregates的升级版)都是对用来约束初始化的精巧的概念

motivation

当我们欲构造如下的union时:

union
{
    int i;
    std::string s;
                    // illegal: std::string is not a POD type!
} u;

vs 2013会对之作进一步的错误说明:

error C2621: “<unnamed-tag>::s: 非法的联合成员;
类型“std::basic_string<char,std::char_traits<char>,std::allocator<char>>”具有复制构造函数 

两者一规约,也即POD数据类型不允许使用其具有复制构造函数;
而且我们还可看到:
所谓的std::string类型其实是对std::basic_string<>某一特化版本的类型定义:

typedef basic_string<char, char_traits<char>, allocator<char> >
    string;

解释:Aggregates vs POD

如果想深入了解 POD(Plain Old Data)的话,了解 aggregates(聚合,集成?) 是必须的。

首先我们来看C++标准对 aggregates 的定义:

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).

也即,首先所有的数组都是Aggregates,然后类类型如果满足那四个条件,等等,标准未对结构体(structs)以及联合体(unions)做任何说明。难道它们就不能成为aggregates了吗?可以的。在C++中,术语(关键字) class 表示所有的类、结构体以及联合。

那么,这四条关于类(class)的约束说明了:

  • 并非意味着一个 aggregate class 不可以拥有构造函数,事实上,它们可以拥有一个默认构造函数(default constrctor)以及(或者)一个拷贝构造函数只有它们被编译器隐式地声明,而非被用户显式地声明。

  • no private or protected non-static data members。You can have as many private and protected member functions (but not constructors) as well as as many private or protected static data members and member functions as you like and not violate the rules for aggregate classes。静态成员可以出现在任何位置,非静态成员只得以公共成员(public)的形式出现。

  • An aggregate class can have a user-declared/user-defined copy-assignment operator and/or destructor。结合第一条,也即如果想要出现构造函数的话,必须以拷贝构造的形式出现(operator=),

  • An array is an aggregate even if it is an array of non-aggregate class type.

下面我们来看一些具体的例子:

class NotAggregate1
{
    virtual void f() {}    // no virtual functions
};

class NotAggregate2
{
    int x;                 // x is private by default and non-static    
};

class NotAggregate3
{
public:
    NotAggregate3(int) {}   // user-defined ctor    
};

class Aggregate1
{
public:
    NotAggregate1 member1;    
                                // ok, public member
    Aggregate1& operator(const Aggregate1& rhs) {// }
                                // ok, copy-assignment
private:
    void f() {}
                                // ok, non-virtual function
};

现在我们来说明,为什么会提出 Aggregate 这样一个概念以及它是如何跟 POD(Plain Old Data)发生关联的?Aggregate 类型的类,可以被初始化通过 {},而non-Aggregate 的 class 不可以。(提出这样一个概念,是为了规范化初始化的用法):

struct X
{
    int i1;
    int i2;
};
struct Y
{
    char c;
    X x;
    int i[2];
    float f;
protected:
    static double d;
    Y& operator=(const Y& rhs) { return *this};
private:
    void g(){}
};

我们可直接使用{}进行初始化:

Y y = {'a', {10, 10}, {20, 30}};
            // y.c = 'a'
            // y.x.i1 = 10
            // y.x.i2 = 10
            // y.i[0] = 20
            // y.i[1] = 30
            // y.f = 0.0 by value-initialized 的方式
            // d 未被初始化,因为它是静态的

POD

来自C++标准:

A POD-struct is an aggregate class that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor. Similarly, a POD-union is an aggregate union that has no non-static data members of type non-POD-struct, non-POD-union (or array of such types) or reference, and has no user-defined copy assignment operator and no user-defined destructor. A POD class is a class that is either a POD-struct or a POD-union.
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.

  • 所有的POD类都必须是Aggregate,或者说,一个类如果不是Aggregate,则一定不是POD类(两者成逆否命题)。

  • 和 Aggregates 的情况一样,静态成员不在乎其具体是什么样的类型(只要是静态的即可),

举个栗子:

struct POD
{
    int x;
    char y;
    void f() {};
                        // no harm if there's a function
    static std::vector<char> v;
                        // static members do not matter
};

struct AggregateButNotPOD1
{
    int x;
    ~AggregateButNotPOD1() {}
                // user-defined destructor
};

struct AggregateButNotPOD2
{
    AggregateButNotPOD1 arrOfNonPOD[3];
                // array of non-POD class
};
  • POD-classes are the closest to C structs. Unlike them, PODs can have member functions and arbitrary static members, but neither of these two change the memory layout of the object. So if you want to write a more or less portable dynamic library that can be used from C and even .NET, you should try to make all your exported functions take and return only parameters of POD-types.
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五道口纳什

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值