问题标签 [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 回答
119 浏览

c++ - 为什么下面的代码也会调用复制构造函数?

为什么当g_Fun()执行到时return temp它会调用复制构造函数?

0 投票
3 回答
803 浏览

c++ - 编译器会在 setter 方法中自动应用移动语义吗?

我想知道是否允许编译器在以下 setter 方法中自动使用 wstring 的移动构造函数(无需显式调用 std::move):

从我读过的内容来看,似乎不允许编译器做出这个决定,因为 str 是一个左值,但很明显在这里使用 move 不会改变程序行为。

除非移动,是否会应用其他类型的复制省略?

0 投票
3 回答
1182 浏览

c++ - How can I disable c++ return value optimization for one type only?

I have come across the situation where I really do need to execute non-trivial code in a copy-constructor/assignment-operator. The correctness of the algorithm depends on it.

While I could disable return value optimisation with a compiler switch, it seems a waste because it's only the one type I need it disabled for, so why should the performance of the whole application suffer? (Not to mention that my company would not allow me to add the switch, anyway).

This class would be used as such:

Return value optimisation means that a4 will not be created with the copy constructor, and the "really important thing to do" does not happen!

I know I could hack in a solution where operator+ returns a different type (B, say) and have an A constructor that takes a B as input. But then the number of operators needed to be implemented explodes:

There must be a better solution. How can I hack it so that RVO does not happen for my type? I can only change the A class code and the operators. I can't change the calling site code; i.e. I can't do this:

One thing I've considered trying is to try and experiment with C++11 move constructors, but I'm not sure this would work, and I don't like it not being valid in C++03.

Any ideas?

EDIT: Please just accept that this is the only way I can do what I need to do. I cannot just 'change the design'. The calling code is fixed, and I must implement my strategy inside the mathematical operators and copy constructor & assignment operator. The idea is that the intermediate values calculated inside the "a4 = (a1+a2)*a3/a1" equation cannot be referenced anywhere else in the program - but a4 can. I know this is vague but you'll just have to live with it.

0 投票
3 回答
232 浏览

c++ - 消除函数参数的复制

我正在编写一个自定义内存分配器。如果可能的话,我想让这样的对象创建功能完全抽象创建过程。

但这会导致复制。在这种情况下,有没有办法强制消除复制?

这是我当前的测试代码。

我试图通过valueas T&, T const&, T&&, T const&&,但它仍然复制。我预计优化器会消除函数框架,因此可以将函数参数推导出为 R 值,但我仍然看到COPY!消息。

我也尝试过 C++11 转发模板,但我不能使用它,因为它不能是一个虚函数。

我的编译器是 Xcode 中包含的 Clang。(clang-425.0.28) 优化级别设置为-Os -flto.

更新(供以后参考)

clang -Os -flto -S -emit-llvm -std=c++11 -stdlib=libc++ main.cpp;我编写了额外的测试,并使用选项检查了生成的 LLVM IR 。我能观察到的是:(1)功能框架总是可以被消除的。(2)如果大对象(4096字节)按值传递,它没有被淘汰。(3) 通过 r 值引用 usingstd::move效果很好。(4) 如果我不制作移动构造函数,编译器大多会退回到复制构造函数。

0 投票
2 回答
130 浏览

c++ - C ++:哪个是要调用的适当构造函数:构造函数还是复制构造函数?

编码

打印"constructor",这很好。现在,当我取消注释复制构造函数时,我得到一个编译时错误:

这可能继续表明这里的复制构造函数将使用一个临时的ElisionTest(10). 并且由于您不能对临时对象进行非常量引用,因此将复制构造函数的参数设为 aconst&应该可以解决该错误。

但是,如果我将复制构造函数修改为 takeconst ElisionTest&而不是ElisionTest&,则没有错误,并且输出"constructor"再次出现。为什么不打印"copy constructor"

0 投票
1 回答
970 浏览

c++ - 为什么标准不强制规定 RVO 和 NRVO?

为什么标准不强制规定 RVO 和 NRVO 优化(当它们适用时)?例如,当一个函数产生一些对象并将其作为结果返回时,这是一种非常常见的情况。由于 RVO/NRVO,复制/移动构造函数通常被省略,但它们仍然需要定义,这有点令人困惑。如果 RVO/NRVO 在标准中,则在这种情况下将不再需要复制/移动构造函数。

0 投票
1 回答
253 浏览

c++ - 在什么情况下,现代编译器不能对函数应用 NRVO 优化?

一般来说,我想知道现代编译器何时以及为什么使用 c++11 的 gcc 4.7 及更高版本不能应用 NVRO 优化。

编辑:我错误地过度简化了这段代码,没有返回任何局部变量。下面的@cooky451 提供了一个更好的示例,请参见ideone.com/APySue

我看到了一些代码片段来回答其他问题

他们被改为

因为他们说传递给左值 v 的右值仍然是右值并且可以移动。然而,其他人写道,这将取消 NVRO 的能力。这是吗?如果编译器知道正在返回一个临时对象,它不能直接在原地构造它而不移动任何东西吗?我想我不明白为什么案例一会有 NVRO 而不是案例 2。我可能有错误的事实,因此问题。另外,由于这个原因,我读到案例 2 是一种反模式,您不应该像这样返回 std::move 。任何额外的见解都会有所帮助。有人告诉我,编译器将在幕后创建如下所示的内容: A&__hidden__是对函数的赋值,在这种情况下是 myValue。

0 投票
1 回答
1874 浏览

c++ - 按值传递和复制省略优化

我遇到了 https://web.archive.org/web/20120707045924/cpp-next.com/archive/2009/08/want-speed-pass-by-value/

作者的建议:

不要复制你的函数参数。相反,按值传递它们并让编译器进行复制。

但是,我不太明白在文章中介绍的两个示例中获得了哪些好处:

对比

在这两种情况下,都会创建一个额外的变量,那么好处在哪里?我看到的唯一好处是,如果将临时对象传递到第二个示例中。

0 投票
3 回答
739 浏览

c++ - 失败时 RVO 强制编译错误

这里有很多关于何时可以完成 RVO 的讨论,但关于何时实际完成的讨论不多。如前所述,RVO 不能根据标准得到保证,但有没有办法保证 RVO 优化成功或相应的代码编译失败?

到目前为止,当 RVO 失败时,我部分成功地使代码问题链接错误。为此,我声明了复制构造函数而不定义它们。显然,在我需要实现一个或两个复制构造函数(即x(x&&)x(x const&).

这就引出了我的第二个问题:为什么编译器编写者选择在用户定义的复制构造函数就位时启用 RVO,而不是在只有默认复制构造函数存在时?

第三个问题:是否有其他方法可以为纯数据结构启用 RVO?

最后一个问题(承诺):你知道任何编译器使我的测试代码表现得比我用 gcc 和 clang 观察到的吗?

以下是显示问题的 gcc 4.6、gcc 4.8 和 clang 3.3 的一些示例代码。该行为不依赖于一般优化或调试设置。当然 option--no-elide-constructors会按照它所说的去做,即关闭 RVO。

输出:

RVO 似乎也不适用于普通数据结构:

输出:

更新:请注意,一些优化很容易与 RVO 混淆。像这样的构造函数助手make_x就是一个例子。请参阅此示例,其中优化实际上是由标准强制执行的。

0 投票
1 回答
349 浏览

c++ - std::pair 移动未在定义中省略?

我注意到 Visual Studio 2012 有一些很奇怪的地方: 像这样定义对对象:

不会在 VC11 中忽略该对的复制/移动,此调用将打印

也就是说,创建一个临时对,然后将其移动到 objp 变量中。(将其声明为pair<...> obj;仅记录默认 ctor)

我已经单独与我的 LogMe 测试对象进行了交叉检查:

这里的任务将被省略。

这似乎是 VC11 特有的,因为在 IDEOne(使用 gcc 4.8.1)中对其进行测试表明,无关的动作总是在那里被忽略。

这里发生了什么? 不能依赖被忽略的初始化副本让我很紧张。

注意:发布与调试版本的测试显示相同的结果。(这是我所预料的,因为复制省略是独立于 MSVC 中的优化标志执行的。)


要测试的完整源代码(另请参见ideone 链接):