安全地移动 C++ 对象 [英] Safely moving a C++ object

查看:46
本文介绍了安全地移动 C++ 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说过一些警告不要通过 memcpy 将对象传送到另一个内存位置,但我不知道具体原因.除非它包含的成员做依赖于内存位置的棘手的事情,否则这应该是完全安全的……或者不是?

I’ve heard some words of warning against shipping an object to another memory location via memcpy, but I don’t know the specific reasons. Unless its contained members do tricky things that depend on memory location, this should be perfectly safe … or not?

预期的用例是一种类似于 vector 的数据结构,它将对象(不是指针到对象)存储在连续的内存块(即数组).要在第 n 个位置插入新对象,从位置 n 开始的所有对象都需要移动,以便为要插入的对象腾出空间.

The contemplated use case is a data structure like a vector, which stores objects (not pointers to objects) in a continuous chunk of memory (i.e. an array). To insert a new object at the n-th position, all objects starting at position n and beyond will need to be moved to make room for the object to be inserted.

推荐答案

为了讨论起见,我假设您的意思是移动意味着原始对象丢弃"(不再使用,没有运行它的析构函数) 而不是有两个副本(这会导致更多问题,引用计数被关闭等).我一般指的是能够按位移动的特性.

For the sake of discussion, I assume you mean moving to mean that the original object "dropped" (is no longer used, didn't have it's destructor run) rather than have two copies (which would lead to a lot more problems, reference counts being off, etc). I generally refer to the property of being able to do this being bitwise movable.

在我处理的代码库中,大多数对象都是按位移动的,因为它们不存储自引用.但是,某些数据结构不能按位移动(我相信 gcc 的 std::set 不能按位移动;其他示例是 链表节点).一般来说,我会避免尝试使用这个属性,因为它会导致一些非常难以调试的错误,并且更喜欢面向对象的调用复制构造函数.

In the code bases I work on, the majority of objects are bitwise movable, as they don't store self references. However, some data structures aren't bitwise movable (I believe that gcc's std::set wasn't bitwise movable; other examples would be linked list nodes). In general, I would avoid attempting to use this property as it can lead to some very hard to debug errors, and prefer the object oriented calling copy constructors.

编辑添加:

对于某人如何/为什么这样做似乎有些困惑:这是我对如何做的评论:

There seems to be some confusion on how/why someone would do this: here's a comment I made on the how:

通常,我会在替代品上看到以上内容向量的实现.记忆通过分配malloc(sizeof(Class)*size) 和对象是通过就地构建的显式调用构造函数和析构函数.有时(比如在重新分配)它们必须被移动,所以选择是做 std::vector 的重复调用复制构造函数关于新内存和析构函数旧的,或者使用 memcopy 并且只是免费"旧块.大多数时候是后者只是有效",但并不适合所有人对象.

Normally, I see the above on alternate implementations of vector. The memory is allocated via malloc(sizeof(Class)*size) and the objects are constructed in place via explicitly called constructors and destructors. Sometimes (like during reallocation) they have to be moved, so the option is to do std::vector's repeated calling of copy constructors on new memory and destructors on the old, or use memcopy and just "free" the old block. Most times the latter just "works", but doesn't for all objects.

至于为什么,memcopy(或realloc)方法可以明显更快.

As to why, a memcopy (or realloc) approach can be significantly faster.

是的,它会调用未定义的行为,但它也往往适用于大多数对象.有些人认为速度值得.如果您真的打算使用这种方法,我建议您实现一个 bitwise_movable 类型特征,以允许将其适用的类型列入白名单,并为不在白名单中的对象使用传统副本,就像示例 这里.

Yes, it invokes undefined behavior, but it also just tends to work for a majority of objects. Some people consider the speed worth it. If you were really set on using this approach, I would suggest implementing a bitwise_movable type trait to allow types this works for to be whitelisted, and fall back on the traditional copy for objects not in the whitelist, much like the example here.

这篇关于安全地移动 C++ 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆