标准布局和不可复制的属性

时间:2012-01-31 10:27:19

标签: c++ c++11 noncopyable standard-layout

C ++ 11,§9/ 7:

  

标准布局类是一个类:

     
      
  • 没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员,
  •   
  • 没有虚函数,也没有虚基类,
  •   
  • 对所有非静态数据成员具有相同的访问控制,
  •   
  • 没有非标准布局基类
  •   
  • 在大多数派生类中没有非静态数据成员,并且最多只有一个具有非静态数据成员的基类,或者没有包含非静态数据成员的基类,并且
  •   
  • 没有与第一个非静态数据成员相同类型的基类。
  •   

那么,有没有办法让标准布局的类不可复制?如果是,怎么样?

从boost :: noncopyable私有地继承是行不通的,因为它使复制构造函数成为私有(因此不是标准布局)。 boost :: noncopyable的实现是这样的:

  class noncopyable
  {
   protected:
      noncopyable() {}
      ~noncopyable() {}
   private:  // emphasize the following members are private
      noncopyable( const noncopyable& );
      const noncopyable& operator=( const noncopyable& );
  };

由于私有部分,它不是标准布局类。我还要注意私有继承是否违反任何标准布局规则。


#include <boost/noncopyable.hpp>
#include <iostream>
const int N = 50;
struct A
{
    int data[N];
};
struct B : private boost::noncopyable
{
    int data[N];
};
struct C
{
    A data[10];
};
struct D : private boost::noncopyable
{
    B data[10];
};

int main() {
    std::cout<<sizeof(A)<<std::endl;
    std::cout<<sizeof(B)<<std::endl;

    std::cout<<sizeof(C)<<std::endl;
    std::cout<<sizeof(D)<<std::endl;
}

输出结果为:

200
200
2000
2004

上面的示例显示从boost::noncopyable私有继承将类更改为NOT标准布局兼容。 我不确定这是否是一个g ++错误(我正在使用g ++ 4.6.1),或者标准被某种方式违反了。

2 个答案:

答案 0 :(得分:4)

我认为这里有一个混乱:

  • 标准布局属性受属性(仅属性)
  • 的影响
  • 可复制属性受方法(它们的存在,缺席和可访问性)的影响

这两个概念是正交的。

<强>更新

以下显示与boost::noncopyable

完全相同的行为
#include <iostream>

struct foo {};

struct B : foo { int data; };

struct D : foo { B data; };

int main() {
  D d;
  std::cout << (char*)(&d.data) - (char*)(&d) << "\n";
}

结果为4

我相信这是因为:

  • 没有与第一个非静态数据成员相同类型的基类。

实际上,实验表明在int a;之前在D中引入data不会增加其大小。我认为B继承自foo这一事实意味着data(第一个非静态数据成员)被认为是与foo相同的类型(基类D)。

这会导致歧义:如果编译器没有引入此填充,foo* f = &d将具有与foo* g = &b.data;相同的地址。

答案 1 :(得分:0)

要使您的课程不可复制,您需要做两件事:

  1. 将复制构造函数设为私有。
  2. 将赋值运算符设为私有。 (它被赋予与类本身相同类型的另一种类型)。
  3. 您不需要继承某些boost类就可以获得该行为。

    我可以补充一下,谁关心一些花哨的'标准布局'的想法。编程你需要的东西,不要屈服于这种极端空间理论。