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 bug(我正在使用g 4.6.1),或者标准是以某种方式被违反的 .
2 回答
我认为这里有一个混乱:
标准布局属性受属性(仅属性)的影响
可复制属性受方法影响(它们的存在,缺失和可访问性)
这两个概念是正交的 .
UPDATE:
以下显示与
boost::noncopyable
完全相同的行为:结果是
4
.我相信这是因为:
实际上,实验表明在
data
之前在D
中引入int a;
并不会增加其大小 . 我认为B
从foo
继承的事实意味着data
(第一个非静态数据成员)被认为是与foo
(D
的基类)相同的类型 .这会导致歧义:如果编译器没有引入此填充,
foo* f = &d
将具有与foo* g = &b.data;
相同的地址 .要使类不可复制,您需要做两件事:
将复制构造函数设为私有 .
将赋值运算符设为私有 . (它被赋予与类本身相同类型的另一种类型) .
你不需要继承一些boost类来获得那种行为 .
我可以补充说,谁在乎一些花哨的“标准布局”的想法 . 编程你需要的东西,不要屈服于这种极端空间理论 .