这将执行默认移动操作吗?
Will this do default move operation
我有一个函数foo:
std::vector<T> foo() {
std::vector<T> result;
// populate result
{
/*
for loop with result.push_back().
ignore real code.
*/
}
//
return result; <-- note there without std::move
}
如果我像下面这样分配,它会做额外的复制吗?
const auto v = foo(); <-- will it move the vector by default?
const auto &v = foo(); <-- same question as above, assuming T is movable
我对第二种情况特别感兴趣,因为对于第一种情况,它是 编译器很可能知道将结果从foo(( 移动到 v。
const auto &v = foo();
对于这种情况,foo(( 函数会创建一个临时结果。现在,由于 v 是引用,因此它无法将结果移动到 v。因此,它需要创建一个新副本。我的理解是对的吗?
通过应用 as-if 规则,允许编译器进行任何和所有不会更改程序可观察行为的代码转换。
但是,copy_elision是as-if 规则的一个例外:编译器可以删除对移动和复制构造函数的调用以及对临时对象析构函数的匹配调用,即使这些调用具有可观察到的副作用。要见证这些副作用,您必须在编译时使用-fno-elide-constructors
选项。
从copy_elision页面,我们应该看一下子句:
在 return 语句中,当操作数是非易失性的名称时 具有自动存储持续时间的对象,这不是函数 参数或 catch 子句参数,并且属于同一类 类型(忽略 CV 限定(作为函数返回类型。这 复制 elision 的变体称为 NRVO,"命名返回值 优化"。
当编译器看到以下结构时,它知道它是 NRVO 的候选项。
T FunctionName ( ... )
{
T a;
...
return a;
}
这与问题的代码结构相匹配。
std::vector<T> foo() {
std::vector<T> result;
// populate result
{
/*
for loop with result.push_back().
ignore real code.
*/
}
return result;
}
个案1 -
const auto v = foo(); <-- will it move the vector by default?
你所看到的不是移动语义,它只是NRVO。
所以这个问题在这里没有任何相关性。
案例2 -
const auto &v = foo(); <-- same question as above, assuming T is movable
T
是否可移动并不重要。这里没有发生move
。
正在发生的概念const &
可以绑定到临时的。
我们也会在 C++11 之前的编译器中实现相同的结果,它没有移动语义支持。
对于这两种情况,似乎都没有额外的副本,从这个链接可以看到
相关文章:
- 复制和交换习惯用法与移动操作之间的交互
- 隐式移动与复制操作和遏制
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 这将执行默认移动操作吗?
- 如何对移动操作进行单元测试(默认)?
- 我是否缺少<实验/文件系统>移动操作?
- 在理解移动语义的同时混淆 c++ 程序中的操作
- 我的移动分配操作程序重载的分段错误
- 是否有可能具有放入容器的移动操作的类型?
- 发送到另一个窗口的鼠标移动消息不执行任何操作
- 我什么时候需要移动操作,c++
- 在'string=string+s1'和"string+=s1"之间移动语义可以保存多少个复制操作?
- 变量可以通过C / C 的左或右移动操作变为null
- 标准::atomic_应该如何...<std::shared_ptr>用于线程安全类的复制和移动操作?
- 命令模式:如何进行连续操作?(例如,移动对象)
- 为什么C++允许您移动包含已删除移动操作的对象的类
- "pair::operator=(pair&&)"错误,"auto&"推断出移动操作 - libstdc++ 回归?
- 移动对象后支持哪些操作?
- 具有可以引发的移动操作的仅移动类的示例是什么?
- Visual Studio 2012 是否正确执行此操作?标准::移动