首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这是一种琐碎的、可复制的结构或任务吗?

这是一种琐碎的、可复制的结构或任务吗?
EN

Stack Overflow用户
提问于 2014-10-03 00:53:11
回答 1查看 2.9K关注 0票数 27

假设您有一个T类型的对象和一个对齐适当的内存缓冲区alignas(T) unsigned char[sizeof(T)]。如果使用std::memcpyT类型的对象复制到unsigned char数组,这是复制构造还是复制分配?

如果一个类型是可以复制的,但不是标准布局,那么可以想象这样的类:

代码语言:javascript
复制
struct Meow
{
    int x;
protected: // different access-specifier means not standard-layout
    int y;
};

可以像这样实现,因为编译器不会被迫使用标准布局:

代码语言:javascript
复制
struct Meow_internal
{
private:
    ptrdiff_t x_offset;
    ptrdiff_t y_offset;
    unsigned char buffer[sizeof(int) * 2 + ANY_CONSTANT];
};

编译器可以将x和Meow的y存储在buffer的任何部分的缓冲区中,甚至可以在buffer中随机偏移,只要它们正确地对齐并且不重叠。如果编译器愿意,xy的偏移量甚至可以随每个构造而随机变化。(如果编译器愿意的话,x可以使用y,因为标准只要求同一个访问说明符的成员按顺序运行,而xy有不同的访问说明符。)

这将满足琐碎可复制的要求;一个memcpy将复制隐藏的偏移字段,因此新的复制将工作。但有些事情行不通。例如,在跨xmemcpy中持有指向memcpy的指针将中断:

代码语言:javascript
复制
Meow a;
a.x = 2;
a.y = 4;
int *px = &a.x;

Meow b;
b.x = 3;
b.y = 9;
std::memcpy(&a, &b, sizeof(a));

++*px; // kaboom

但是,编译器真的允许以这种方式实现一个琐碎的可复制类吗?只有在basic.life/1的生命周期结束的情况下,销毁px才应该是未定义的行为。是吗? N3797标准草案的相关部分在这个问题上并不十分清楚。这是节a.x

对象的生存期是对象的运行时属性。如果一个对象是一个类或聚合类型,并且它或它的一个成员被一个构造函数初始化,而不是一个普通的默认构造函数,那么它就被称为具有非平凡的初始化。注意:通过简单的复制/移动构造函数进行初始化是非常重要的初始化。-结束注意T类型对象的生存期从以下时间开始:

  • 获得了T类型的适当对齐和大小的存储,并且
  • 如果对象具有非平凡的初始化,那么它的初始化就完成了.

类型为T的对象的生存期结束时:

  • 如果(class.dtor),是具有非平凡析构函数T的类类型,则析构函数调用启动,或
  • 对象所占用的存储被重用或释放。

这是basic.types/3

对于任何普通可复制类型(intro.memory)的对象(基类子对象除外),无论该对象是否持有T类型的有效值,组成该对象的底层字节都可以复制到charunsigned char数组中。如果将charunsigned char数组的内容复制回对象中,则该对象随后将保持其原始值。示例省略

然后问题就变成了,是对一个琐碎的可复制类实例的memcpy覆盖“复制构造”还是“复制分配”?问题的答案似乎决定了Meow_internal是否是编译器实现琐碎的可复制类Meow的有效方式。

如果memcpy是“复制构造”,那么答案是Meow_internal是有效的,因为复制构造正在重用内存。如果memcpy是“复制分配”,那么答案是Meow_internal不是有效的实现,因为赋值不会使指向类实例化成员的指针失效。如果memcpy两者兼而有之,我不知道答案是什么。

EN

回答 1

Stack Overflow用户

发布于 2015-05-08 00:45:58

在同一草案中,您还可以找到以下案文,与您引用的文本直接对应:

对于任何可复制的T类型,如果指向T的两个指针指向不同的T对象obj1obj2,其中obj1obj2都不是基类子对象,则如果组成obj1的底层字节(1.7)被复制到obj2中,则obj2随后将保持与obj1相同的值。

请注意,这说明了obj2值的更改,而不是销毁对象obj2并在其位置创建一个新对象。因为不是对象,而只是它的值被更改,因此对其成员的任何指针或引用都应该保持有效。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26171827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档