问题标签 [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 投票
3 回答
985 浏览

c++ - Visual C++ 2010 Beta 2 上的复制省略

我在读想要速度?C++ Next 博客上通过值传递并创建了这个程序来感受 C++0x 中的复制省略和移动语义:

这是我在 Visual C++ 10.0(Beta 2)上以发布模式编译时得到的输出:

从 RVO 移动分配:
构造实例 1(无数据)
构造实例 2(有数据)
从移动 2 构造实例 3
销毁实例 2
从 3 分配给实例 1
销毁实例 3
销毁实例 1
移动省略:否

从 RVO 简单移动分配:
构造实例 1(无数据)
构造实例 2(使用简单数据)
从 2 分配给实例 1
销毁实例 2
销毁实例 1
移动省略:是

从 NRVO 移动分配:
构造实例 1(无数据)
构造实例 2(有数据)
从 2 分配给实例 1
销毁实例 2
销毁实例 1
移动省略:是

从 NRVO 简单移动分配:
构造实例 1(无数据)
构造实例 2(使用简单数据)
从 2 分配给实例 1
销毁实例 2
销毁实例 1
移动省略:是

但是,我对一件事感到困惑。如您所见,除了第一个动作之外,所有动作都被省略了。为什么编译器不能在第 86 行使用 MoveableClass(std::vector) 执行 RVO,但可以在第 97 行使用 MoveableClass(int)?这只是 MSVC 的错误还是有充分的理由?如果有充分的理由,为什么它仍然可以在第 91 行对 MoveableClass(std::vector) 执行 NRVO?

我想了解它,这样我才能快乐地入睡。:)

0 投票
2 回答
9664 浏览

c++ - 什么是复制省略,它如何优化复制和交换的习惯用法?

我正在阅读Copy and Swap

我尝试阅读有关 Copy Elision 的一些链接,但无法正确理解它的含义。有人可以解释一下这个优化是什么,特别是下面的文字是什么意思

这不仅仅是方便的问题,实际上也是一种优化。如果参数(s)绑定到左值(另一个非常量对象),则在创建参数时会自动制作对象的副本。但是,当 s 绑定到右值(临时对象,文字)时,副本通常会被省略,这样可以节省对复制构造函数和析构函数的调用。在参数被接受为 const 引用的赋值运算符的早期版本中,当引用绑定到右值时,不会发生复制省略。这会导致创建和销毁一个额外的对象。

0 投票
2 回答
433 浏览

c++ - 自动变量的复制删除以返回

我想知道当复制省略发生时,是否在 C++0x “ 12.8复制和移动类对象 [class.copy] 第 31 段”中:

当满足某些标准时,允许实现省略类对象的复制/移动构造[...]。这种复制/移动操作的省略,称为复制省略,在以下情况下是允许的 [...]:

  • 在具有类返回类型的函数的返回语句中,当表达式是具有与函数返回类型相同的 cv 非限定类型的非易失性自动对象 [...] 的名称时,复制/移动操作可以通过将自动对象直接构造到函数的返回值中来省略
  • [...]

现在我想知道,这是否允许在以下代码中逃避复制

还是该规则适合示例,我必须明确说明?

请注意,我的意图if是消除明显的返回值优化(RVO)。

还是我在这里完全走错了路?有一个涉及returnmove的更改可以使用rvalue references,对吗?

0 投票
3 回答
1095 浏览

c++ - 编译器可以省略以下副本吗?

我仍然是一个新手程序员,我知道过早的优化是不好的,但我也知道复制大量的东西也是不好的。

我已经阅读了复制省略,它是同义词,但是例如 Wikipedia 上的示例让我觉得只有当要返回的对象在完全构造的同时返回时才会发生复制省略。

像向量这样的对象呢,通常只有在填充某些东西时才有意义,当用作返回值时。毕竟,空向量只能手动实例化。

那么,在这种情况下它是否也有效?

简洁的坏风格:

我在使用 bar(vector & out, string text) 时没有真正的麻烦,但上述方式在美学和意图上看起来要好得多。

0 投票
3 回答
897 浏览

c++ - 是否可以确保复制省略?

复制省略是一种巧妙的优化技术,在某些情况下,依赖复制省略实际上比“手动”传递引用要快。

因此,让我们假设您已经确定了一个关键代码路径,您依靠编译器执行复制省略这一事实来获取代码路径以获得最佳性能。

但是现在您依赖于编译器优化。

是否有任何(编译器特定的,显然)方法来确保实际执行复制省略并在无法执行复制省略时让编译器(或其他工具)生成警告/错误?

(我正在考虑一些与 Visual C++ 很相似的东西,__forceinline如果这样标记的函数没有被编译器内联,则会生成警告。)

0 投票
5 回答
492 浏览

c++ - 传递重物 C++0x

我有一个函数可以生成一种昂贵的对象(包含向量和非固定大小的地图),所以我真的想避免调用复制 c'tors。

到目前为止,我刚刚从该方法返回了一个 std::shared_ptr 并使用了它,但我认为它很难看,需要 typedefing 才能真正可用。

我知道两件事可能对我有帮助。首先是复制省略,其次是移动语义。

我的问题是我知道如何正确使用它们。我的研究告诉我,复制省略完全由编译器完成,而不是标准的一部分。我真的不想仅仅依靠这个。

那么我如何确保调用移动分配并使其到位以防止编译器复制省略。

在这种情况下,这是最正确的编码方式吗?如果不是,我该如何改进它。我很高兴只使用 C++0x 结构。

顺便说一句:我的编译器是 gcc 4.6

0 投票
1 回答
250 浏览

c++ - 在 C++0x 中避免移动/复制的更好方法

这个问题来自How to pass by lambda in C++0x? ,但也许这是一种更清晰的提问方式。

考虑以下代码

输出以下内容:

很明显,宏版本以某种方式省略了所有移动/复制构造函数调用,但函数版本没有。

我假设在 C++0x 中没有大量宏的情况下,有一种语法上很好的方法可以省略所有移动和副本,但我想不通。

原因:

我计划使用这样的代码,无需移动或复制来构建参数包,即

并且与非参数代码相比,这些没有额外的移动/副本。

0 投票
3 回答
294 浏览

c++ - 复制省略可以发生在 catch 语句中吗?

考虑一个带有副作用的复制构造函数的异常类。

编译器可以在这里跳过调用复制构造函数吗:

那这个呢:

(是的,我知道这一切都很丑陋,这是受另一个问题的启发)

0 投票
2 回答
1359 浏览

c++ - 复制构造函数省略?

可能重复:
为什么只调用了一次析构函数?

鉴于下面的代码,我无法理解 gcc 中的输出。我希望创建和销毁两个对象,但只看到一个对构造函数和析构函数的调用。这里发生了什么事?

此代码在 g++ (4.4) 中的输出是

输入 g

构造函数

退出 g

离开主线前

析构函数

0 投票
2 回答
1002 浏览

c++ - 为什么 / NRVO 在下面的代码中不使用 g++?

我一直在研究 NRVO,它对不同编译器的支持,遇到了奇怪的行为,这很令人困惑。

示例代码:

使用优化级别 2(或 3)编译后,输出是 2 个不同的内存地址。虽然,据我了解,功能代码对 NRVO 有效。

PS 使用 VS2010 和优化级别 2 编译的相同代码使用 NRVO。

如果我添加额外的构造函数:

编译地址相同后,我假设应用了 NRVO,但它与优化级别无关。

X(const X& h) ”是否以某种方式暗示 g++ 使用 NRVO?或者根本没有应用 NRVO,它有什么不同?

提前致谢。

添加。海合会版本:

$ g++ -v

Configured with: [....] -enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu

gcc version 4.4.3

附加测试:使用X(const X& h)构造和-fno-elide-constructorsg++ 标志编译它调用“复制”构造函数,预期行为。没有它,NRVO 就会失败。在不同的机器上测试:gcc 4.4.3 和 gcc 4.3.* -> 相同的结果。

到目前为止,我不确定 __cxa_atexit (存在于 @yves 的 g++ 版本中)是否会以某种方式影响不同的行为。(据我了解,这与它无关,但我不完全理解它给调用顺序带来的变化)