标准布局和不可复制的属性
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
私有继承会将类更改为不符合标准布局。 我不确定这是否是 g++ bug(我使用的是 g++ 4.6.1),或者以某种方式违反了标准。
C++11, §9/7:
A standard-layout class is a class that:
- has no non-static data members of type non-standard-layout class (or array of such types) or reference,
- has no virtual functions and no virtual base classes,
- has the same access control for all non-static data members,
- has no non-standard-layout base classes,
- either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members, and
- has no base classes of the same type as the first non-static data member.
So, is there a way to make a class with standard layout non-copyable? If yes, how?
Inheriting privately from boost::noncopyable will not work, because it made copy constructor private (hence not a standard layout). The boost::noncopyable's implementation is like this :
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
Because of the private section, it is not a standard layout class. I am also note sure if private inheritance break any standard layout rule.
#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;
}
The output is :
200
200
2000
2004
The example above shows that inheriting privately from boost::noncopyable
changes the class into NOT standard layout compliant.
I am not sure if this is a g++ bug (I am using g++ 4.6.1), or the standard is somehow violated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为这里存在一个混淆:
这两个概念是正交的。
更新:
以下内容显示与
boost::noncopyable
完全相同的行为:结果是
4
。我相信这是因为:
事实上,实验表明,在
data
之前在D
中引入int a;
并不会增加其大小。我认为B
继承自foo
的事实意味着data
(第一个非静态数据成员)被认为是与foo
(D
的基类)。这会导致歧义:如果编译器没有引入这个,
foo* f = &d
将与foo* g = &b.data;
具有相同的地址填充。I think there is a confusion here:
The two concepts are orthogonal.
UPDATE:
The following display the very same behavior that
boost::noncopyable
:The result is
4
.I believe this is because of:
Indeed, experiment shows that introducing a
int a;
inD
prior todata
does not increases its size. I think that the fact thatB
inherits fromfoo
means thatdata
(first non-static data member) is considered to be the same type asfoo
(base class ofD
).This leads to an ambiguity:
foo* f = &d
would have the same address asfoo* g = &b.data;
if the compiler did not introduce this padding.要使类不可复制,您需要做两件事:
您不需要仅仅为了获得该行为而继承某个 boost 类。
我可以补充一下,谁会关心一些奇特的“标准布局”想法。编写您需要的内容,不要屈服于这种极端的空间理论。
There are two things you need to do to make your class non copyable:
You don't need to inherit from some boost class just to get that behavior.
And may I add, who cares about some fancy 'standard layout' idea. Program what you need and don't succumb to this extreme space theory.