问题标签 [copy-elision]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
559 浏览

c++ - 保证省略和链式函数调用

假设我有以下类型:

我有声明(假设所有命名变量都是左值类型X):

在 C++17 中,我对这个表达式将执行多少个副本和移动有什么保证?非保证省略怎么办?

0 投票
4 回答
8389 浏览

c++ - 如何就地初始化数组?

如何在不复制或移动构造临时元素的情况下初始化数组?当元素具有显式deleted 复制或移动构造函数时,只有当元素具有默认 ctor 或具有所有默认参数的 ctor 并且我执行以下操作之一时,我才能初始化数组:(a)明确声明数组,(b ) 直接初始化和零初始化数组,或 (c) 复制初始化和零初始化数组。直接(但不是零)初始化和复制(但不是零)初始化都不会编译。

  1. 这 3 种方法是在不复制/移动临时元素的情况下初始化数组的唯一方法吗?
  2. a1将,a2a3count 作为初始化吗?ega1是一个声明,但它的元素获取初始值,尽管是默认值。
  3. 他们中的任何一个都是错误吗?我用 C++14 标志做了这个 GCC 6.3.0。
  4. 为什么复制初始化结合零初始化仍然在复制初始化的范畴下工作?
  5. 一般来说,所有带有花括号的数组初始化都只是临时元素的构造(除非在没有删除复制或移动构造函数时省略(或者省略不适用于数组?)),然后是每个元素的复制、移动或混合复制和移动构造?
0 投票
1 回答
375 浏览

c++ - C++11 复制 elison 和异常(catch 参数)

经过代码审查后,我们在 try/catch 块中遇到了复制 elison 的问题。阅读本页后: cpp 参考指南,尤其是本段:

处理异常时,如果 catch 子句的参数与抛出的异常对象属于同一类型(忽略顶级 cv 限定),则省略副本,并且 catch 子句的主体直接访问异常对象,如如果被引用捕获

我认为 catch 中参数的复制省略会自动执行,但是其中一位审阅者运行了一个简单的测试,表明编译器没有执行复制省略:

编译时:

我得到以下输出

我期待一个类似于(抛出异常时只调用一次复制构造函数)的输出:

测试已在 Linux Ubuntu 16.04 下运行 g++ 版本:

是测试用例无效还是我对复制省略的理解有误?非常感谢您的帮助

0 投票
3 回答
164 浏览

c++ - 左值和右值返回类型以提高效率

更新:

  1. 因此,根据 Jean 的评论,我查看了此链接。这实际上非常接近我要问的问题。唯一的区别是它明确地处理类(这cv::UMat无疑是);

    但是,我尝试对返回类型进行的功能嵌套是否仍然有效?是否仍会出现复制省略,并达到预期的结果?


问题

我目前正在使用 OpenCV 的cv::UMat对象类,我的同事编写了一个函数来进行cv::UMat添加,如下所示:

现在,如果我这样称呼它,这很好用:

但是,当我尝试将函数作为参数传递给函数时,出现“参数必须是左值”类型错误。例如,

对于任何有效cv::UMats的 , alpha, beta

至今

我做了一些研究,发现它std::move(input)显式地返回了一个右值类型的临时值。因此,抛出错误是有道理的。

我意识到我可以通过首先执行以下操作来解决此问题:

或者,我什至可以做类似的事情,

在这种情况下,我的理解是该行将return returnMat导致一个 deep(?) 临时被复制。

问题

所以,我知道这里可能会发生一些依赖于 OpenCV 的事情;就像,也许是因为 UMat 类型正在进行一些时髦的铸造等。

但是,在一般情况下,适应函数的最佳方法 addUmats能够将函数作为对函数的调用?

在运行时方面,我将寻求最有效的解决方案。另外,我不希望这个问题仅限于 OpenCV 案例;获得使用该std::move(input)调用的任何类型函数的答案将不胜感激。

0 投票
1 回答
475 浏览

c++ - 为什么for_each通过移动返回函数

我正在阅读std::for_each这里的文档http://en.cppreference.com/w/cpp/algorithm/for_each并看到返回值是std::move(f)

为什么标准强制在返回值中移动输入参数?由于输入参数是按值传递的,所以默认情况下不会移动它吗?


当您编译以下代码时,这导致我进行了一些后续操作

  1. return 语句是在我的系统上具有最高优化级别 ( -O3) 的移动,为什么大多数编译器不忽略这个返回值?局部值被省略,但函数参数不是..

  2. 在这种情况下,C++17 是否强制省略?我阅读了该提案(http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html),但我不完全了解哪些情况符合强制省略的条件。

我已经Apple LLVM version 8.0.0 (clang-800.0.42.1)在我的 Mac 和g++ 5.4Ubuntu 16.04 上尝试过这个。

0 投票
2 回答
54 浏览

c++ - const 引用来延长对象的生命,然后是 const_cast,这是个好主意吗?

考虑以下返回大对象的函数:

我想得到清单,而不是它的副本。因为如果我必须复制这样的对象,性能代价是昂贵的。我知道返回值优化可能会为我解决这个问题,但是依靠优化来优化坏代码并不是最好的方法(对吧?)。

避免复制和延长对象寿命的一种干净方法是使用常量引用(请在将其称为悬空引用之前对其进行测试,因为它不是):

在 C++11 中,可以std::move用来避免复制。但是,我正在开发一个 C++03 程序,我必须这样做:

现在我需要将列表拼接在一起。我这样做的唯一方法是复制所有内容,或者const_cast这些列表并将它们拼接起来。有更好的解决方案吗?

0 投票
1 回答
79 浏览

c++ - 返回复制的对象

在如下函数中:

编译器可以轻松执行 RVO,因此请执行以下操作:

但是,我已经看到第二种方式有时比前者更可取,例如在 STL 算法实现 (gcc) 中,我想知道这是否会以任何方式(如std::move(*it)std::move(tmp)确实)影响 RVO,或者有任何其他原因,因为例如,关于转换或其他任何事情。

例如reserver_iterator,,而不是:

用途:

我之所以这么问,是因为为了实现类似 的重载operator+,我广泛使用了以下模式:

代替:

这并不是特别具有可读性,但使它长了 3 行(一行中的这两个句子会很丑)。

0 投票
1 回答
1242 浏览

c++ - 如何强制调用移动构造函数,我为什么要这样做?

我测试了这段代码,看看编译器会自动将临时对象传输到变量,而不需要移动构造函数。

此代码打印“Hi from default from getA”,而不是假定的“Hi from move”

在优化方面,它很棒。但是,如何在不添加副本的情况下强制调用移动构造函数?(如果我想要临时对象的特定行为)

补充问题:我认为,如果我没有编写移动构造函数,那么每次我将右值分配给左值时都会有一个副本(就像在该行的代码中一样A b(getA());)。既然情况并非如此,而且编译器似乎做得很好,那么实现移动语义什么时候真正有用?

0 投票
0 回答
40 浏览

c++ - 返回对象的函数未执行深度复制。为什么 foo() 返回的 temp 没有被深度复制?

** foo() 返回的临时对象不会被复制。在 this 中调用普通构造函数,但不调用复制构造函数。谁能指出我到底哪里出错了。**

0 投票
2 回答
915 浏览

c++ - 保证复制省略是否适用于函数参数?

如果我理解正确,从 C++17 开始,这段代码现在要求不进行任何复制:

函数参数也是如此吗?副本会在以下代码中被优化掉吗?