移动语义是否不完整? [英] Are move semantics incomplete?

查看:121
本文介绍了移动语义是否不完整?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在复制效率不高的情况下,移动语义会替换复制语义.复制语义完全处理可复制对象,包括const对象.

Move semantics replace copy semantics in situations where copying is inefficient. Copy semantics deals fully with copyable objects, including const objects.

在c ++ 11中已经存在无数不可复制的对象,例如std :: unique_ptr.这些对象完全依赖于移动语义,因为从一个对象移动会使其无效.这对于像RAII这样的流行设计模式来说很重要(imho).

Already, there exists a myriad of non-copyable objects in c++11, for example std::unique_ptr. These objects rely on move semantics completely because moving from an object allows for invalidating it. This is important (imho) for popular design patterns like RAII.

将const不可复制对象分配给内存区域时,会发生问题.这样的对象无法以任何方式恢复.

A problem occurs when a const non-copyable object is assigned to an area of memory. Such an object can't be recovered in any way.

由于对象的恒定性,这在对象的生存期内显然很重要.在生命周期的尽头,然而,当调用析构函数时,(不存在)对象只是短暂的非常量对象.

This is obviously important during the lifetime of the object, because of its constness. At the end of it's lifetime, when the destructor is called however, the (non-existent) object is briefly non-const.

我建议 moving 析构函数可能是对move语义模型的宝贵补充.

I suggest that a moving destructor could be a valuable addition to the move semantics model.

考虑一个简单的情况,在unordered_set中使用unique_ptr.您可以使用move构造函数(或构造"emplace")将insert放入此集合,但是,如果您想将此指针移动到另一个unordered_set(即保持其const),将是不可能的.

Consider a simple situation where an unique_ptr is used in an unordered_set. You can insert into this set using a move constructor (or construct "emplace"), however if you wanted to move this pointer to another unordered_set (i.e. keeping it const) it would be impossible.

基本,有一个iterator insert((possibly const) key&&)但没有const key&& erase(iterator).实际上这是不可能的.只能扩展该容器以返回指向该键的一些指针,而不必理会它.

Essential, there is a iterator insert((possibly const) key&&) but no const key&& erase(iterator). In fact it would be impossible. The container could only be extended to return some pointer to the key, and forget about it.

移动的析构函数可以解决此问题,即const MyClass&& ~MyClass(),因为它只会在销毁过程中(当编译器认为该对象仍然无效时)违反const.

A moving destructor could solve this ie const MyClass&& ~MyClass(), since it would only violate const during destruction (when the compiler considers the object is invalid anyway).

我应该指出const MyClass&& ~MyClass() const实际上更有意义.析构函数不必修改任何内容,只需销毁对象,就好像它不再是对其控制的任何资源的有效句柄一样.

I should point outconst MyClass&& ~MyClass() const actually makes more sense. The destructor doesn't have to modify anyhting, only destroy the object as if it were no longer a valid handle to whatever resource it controlled.

推荐答案

Imho您已经确定了真正的需求.

Imho you have identified a real need.

您的解决方案听起来很像我所说的破坏性移动语义.

Your solution sounds a lot like what I have called destructive move semantics. This possibility is described in the original move semantics proposal. I think such a design is possible, though it is not without its problems. As far as I know, no one is working this area on the standards committee.

有一些更简单的方法可以从关联容器中提取仅移动类型,而无需更改语言(除了允许在没有未定义行为的情况下进行类型修饰之外).

There are simpler ways to extract move-only types out of the associative containers that would not require language changes (aside maybe from allowing type-punning without undefined behavior).

N3645 是仅库建议,将嵌套的node_ptr类型放入每个容器中. node_ptr非常类似于unique_ptr.它在关联容器中具有节点的唯一所有权.但是,当取消引用它时,您将获得对节点中的value_type的非常量访问,而不是节点本身. extractinsert成员被添加到关联的容器中,从而使一个成员可以向容器中插入节点(由node_ptr拥有)或从中删除节点.

N3645 is a library-only proposal which puts a nested node_ptr type into each container. The node_ptr is a lot like a unique_ptr. It has unique ownership of a node in an associative container. But when you dereference it, you get non-const access to the value_type in the node, instead of the node itself. extract and insert members are added to the associative containers allowing one to insert and remove nodes (owned by the node_ptr) to/from the containers.

您可以使用它从容器中删除节点,然后将仅移动类型移出该节点,并在完成操作后让~node_ptr()清理该节点.本文包含了用于演示此功能的示例:

You could use this to remove a node from a container, and then move a move-only type out of the node, and let ~node_ptr() clean up the node when you are done with it. The paper includes this example to demonstrate this functionality:

set<move_only_type> s;
s.emplace(...);
move_only_type mot = move(*s.extract(s.begin())); // extract, move, deallocate node

请注意,s.extractnoexcept,当然也是~node_ptr().如果move_only_type的移动结构为noexcept,则整个操作为noexcept.否则,如果抛出移动构造,则将set保留为已从set中删除该项目.

Note that s.extract is noexcept, as is ~node_ptr() of course. If the move construction of move_only_type is noexcept, then this whole operation is noexcept. Otherwise if the move construction throws, the set is left as if the item had been erased from the set.

目前,

At the moment, no progress is being made on N3645. It has not been voted into a working draft, and I have no confidence that it ever will be.

更新C ++ 17

我已纠正:上面描述的功能已通过

I stand corrected: The functionality I describe above was voted into C++17 with P0083R3. Thanks to Cosme for reminding me of this in the comments below.

这篇关于移动语义是否不完整?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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