Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 移动语义是否不完整?_C++_C++11_Language Features_Move Semantics - Fatal编程技术网

C++ 移动语义是否不完整?

C++ 移动语义是否不完整?,c++,c++11,language-features,move-semantics,C++,C++11,Language Features,Move Semantics,在复制效率低下的情况下,移动语义取代复制语义。复制语义完全处理可复制对象,包括常量对象 在c++11中已经存在大量不可复制的对象,例如std::unique\u ptr。这些对象完全依赖于移动语义,因为从对象移动可以使其无效。这对于像RAII这样的流行设计模式很重要(imho) 将常量不可复制对象分配给内存区域时会出现问题。这样的物体无论如何都无法恢复 这在对象的生命周期中显然很重要,因为它是常数。然而,在它的生命周期结束时,当调用析构函数时,(不存在的)对象短暂地是非常量的 我认为移动析构函数

在复制效率低下的情况下,移动语义取代复制语义。复制语义完全处理可复制对象,包括常量对象

在c++11中已经存在大量不可复制的对象,例如std::unique\u ptr。这些对象完全依赖于移动语义,因为从对象移动可以使其无效。这对于像RAII这样的流行设计模式很重要(imho)

将常量不可复制对象分配给内存区域时会出现问题。这样的物体无论如何都无法恢复

这在对象的生命周期中显然很重要,因为它是常数。然而,在它的生命周期结束时,当调用析构函数时,(不存在的)对象短暂地是非常量的

我认为移动析构函数可能是移动语义模型的一个有价值的补充

考虑一个简单的情况,在一个无序的集合中使用一个唯一的\u ptr。您可以使用移动构造函数(或构造“emplace”)将
插入到该集合中,但是如果您想将该指针移动到另一个无序集合(即保持不变),则不可能

重要的是,有一个
迭代器插入((可能是常量)键&&)
,但没有
常量键&&erase(迭代器)
。事实上,这是不可能的。容器只能扩展为返回一些指向键的指针,而忽略它

移动析构函数可以解决这个问题,即
const MyClass&&~MyClass()
,因为它只会在销毁过程中违反const(当编译器认为对象无论如何都无效时)


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

对不起,前提是有缺陷的

无序集
实际上并不包含
常量
对象。它只是不允许您对包含的元素进行写访问。这只是访问者的属性

可以添加一个
键擦除(迭代器)
函数,该函数只将元素移出到临时位置。我不知道你为什么想要一个
键&&


至于
const MyClass&&~MyClass()const
,这没有意义,原因有三:DTR既没有返回类型,也没有CV分类,也没有为它们完成重载解析。

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

你的解决方案听起来很像我所说的破坏性移动语义。此可能性在中描述。我认为这样的设计是可能的,尽管它并非没有问题。据我所知,没有人在标准委员会的这个领域工作

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

是一个仅用于库的方案,它将嵌套的
节点\u ptr
类型放入每个容器中。
节点\u ptr
非常类似于
唯一的\u ptr
。它具有关联容器中节点的唯一所有权。但是,当您取消引用它时,您可以对节点中的
值类型
进行非常量访问,而不是节点本身<代码>提取
插入
成员添加到关联容器中,允许在容器中插入和删除节点(属于
节点_ptr

您可以使用此选项从容器中删除节点,然后将仅移动类型移出该节点,并在使用完节点后让
~node_ptr()
清理该节点。本文包括此示例以演示此功能:

set<move_only_type> s;
s.emplace(...);
move_only_type mot = move(*s.extract(s.begin())); // extract, move, deallocate node
set;
s、 侵位(…);
move_only_type mot=move(*s.extract(s.begin());//提取、移动、取消分配节点
请注意,
s.extract
noexcept
,当然也是
~node_ptr()
。如果
move_only_type
的移动构造为
noexcept
,则整个操作为
noexcept
。否则,如果移动构造抛出,则将保留
集合
,就像该项已从
集合
中删除一样

目前,在这方面没有取得任何进展。它还没有被表决成为一项工作草案,我也不相信它会成为

更新C++17

我的观点是正确的:我上面描述的功能是通过投票进入C++17的。感谢Cosme在下面的评论中提醒我这一点。

那么基本上你是说应该可以将一个
const
对象移动到另一个
const
对象中并销毁原始对象

很抱歉,但我认为将其设置为const的整个要点是防止出现这种情况

否则它将形成一个漏洞:您可以销毁并将一个
const
对象移出其内存位置,然后销毁并将另一个
const
对象移动到第一个对象的内存位置(通过放置
new

现在,对象已更改,即使它是
常量
。。。所以本质上,
const
是无用的


请参阅下面的评论…

Const对象在构建过程中也是非
Const
对象。更合适的论坛是本页前两个论坛之一:本质上,它只将需要的内容(这是移动在c++11中的意思)复制到新对象中,然后销毁旧对象,就像正常移动一样,但是发生的不是为了一个非-temp@BenjaminLindley“是的,我想我不想讨论太多‘不可能’或‘类似于这个提议’@BenjaminLindley我把这个问题贴在了其他地方,时间会告诉我这里是否有人想删除它,或者回答它(或者,你知道,向上投票……),当然这没有意义