Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/128.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++;11过度抄写习语?_C++_C++11_Idioms - Fatal编程技术网

C++ 是否移动C++;11过度抄写习语?

C++ 是否移动C++;11过度抄写习语?,c++,c++11,idioms,C++,C++11,Idioms,我在这里可能会感到困惑,但我所理解的是: COW将返回一份“假”副本,直到其中一个呼叫者想要进行一些修改 Move Semantic在所有情况下都将返回“假”副本 >如果我的目的是有一个对象只需要被读取而不更新,我只需要等待C++编译器中的移动语义支持() 我说得对吗 谢谢:)移动语义不会返回“假”副本。相反,在复制操作中,它授予被复制者销毁原始副本的权限 一个激励性的例子可能很有启发性: std::vector<int> bigData; // fill bigData

我在这里可能会感到困惑,但我所理解的是:

  • COW将返回一份“假”副本,直到其中一个呼叫者想要进行一些修改
  • Move Semantic在所有情况下都将返回“假”副本
<> >如果我的目的是有一个对象只需要被读取而不更新,我只需要等待C++编译器中的移动语义支持(

) 我说得对吗


谢谢:)

移动语义不会返回“假”副本。相反,在复制操作中,它授予被复制者销毁原始副本的权限

一个激励性的例子可能很有启发性:

std::vector<int> bigData;

// fill bigData

std::vector<std::vector<int> > listOfData;

listOfData.push_back(std::move(bigData));
// after this point, the contents of bigData are unspecified (however accessing it is _not_ undefined behavior)
std::vector bigData;
//填充大数据
std::向量列表数据;
listOfData.push_back(std::move(bigData));

//在这一点之后,bigData的内容是未指定的(但是访问它是_不是u未定义的行为)
如果没有移动语义,您需要复制
bigData
以将其插入listOfData,或者手动使用
swap()
将其旋转到listOfData中的新空向量中。但是使用移动语义,
std::vector
的右值引用构造函数(又称移动构造函数)在复制新数据时由
push_back
调用,它有权丢弃
bigData
的旧内容,例如,它可以窃取
bigData
的内部指针,并将
bigData
重置为空向量

移动语义通常比COW语义更快,因为它们不需要维护对共享只读数据的引用计数。但是,它们的局限性更大——您不能使用移动语义为数据创建多个引用计数别名,您可以轻松方便地在容器之间移动数据


还注意到GCC和微软Visual C++的两个版本都支持RValk引用和移动语义(GCC与)——STD= C++ +0x,所以没有理由不在今天开始使用它们。

< P>写和移动构造函数的复制是不同的。 让我们谈谈COW实现广泛使用的字符串。假设您有支持COW和move语义的字符串实现。然后考虑这个代码:

cow::string foo() { return string("foo"); } // move CTOR is in effect here.

cow::string a = foo(); // move ctor in effect
cow::string b = a; // copy ctor in effect
a
b
将共享相同的分配字符序列。在这里

std::string foo() { return string("foo"); } // move CTOR is in effect here.

std::string a = foo(); // move ctor in effect
std::string b = a; // copy ctor in effect

a
b
将分配和保存两个不同的字符序列,使内存消耗翻倍

定义垃圾:未知但有效的状态。“bigData的内容未指定(但访问它不是未定义的行为)”-因此结果是由复制的类型在其移动构造函数中定义的?如果没有定义移动构造函数,
std::move
是否会退回到复制构造函数?或者在
std::swap
上?@KarlKnechtel:
std::move
不会移动任何东西。它所做的只是将其转换为
T&
r值引用,这可以触发调用move构造函数(或move赋值操作符)。是move构造函数实际执行移动操作。将创建默认移动构造函数,就像创建默认复制构造函数一样。默认的move构造函数单独移动每个元素。对于基本类型,默认移动只是一个副本。对于用户定义的类型,这是对移动构造函数的调用。我的理解是,字符串的COW实现虽然显而易见,但实际上并不普遍,因为人们发现它们会破坏多线程环境中的性能。Karl,你有任何实际的证明吗“它们会破坏多线程环境中的性能"? 这些处理器听起来像是都市神话。是的,InterlockedCrement&friends确实会产生一些开销,但在多线程环境中,额外的堆分配也需要一些同步原语。更糟糕的是什么还不清楚。在任何情况下,这都取决于具体情况。我用“我的理解是那样的”和“其他人发现了”这样的短语来表达我的观点是有充分理由的我们在COW、动态内存分配和锁方面的经验不好。COW字符串在多线程环境中并不总是好的