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

c++ - C++ 返回值优化

这段代码:

我在这里的错误理解是函数 getstdvec 不应该实际分配它返回的向量。当我在 valgrind/callgrind 中运行它时,我看到有 1001 次调用 malloc;main 中的初始向量声明为 1,每次循环迭代为 1000。

是什么赋予了?如何从这样的函数返回向量(或任何其他对象)而不必每次都分配它?

编辑:我知道我可以通过引用传递向量。我的印象是可以(甚至更可取)编写这样的函数来返回一个对象而不会产生不必要的分配。

0 投票
1 回答
781 浏览

c++ - 复制/移动省略与显式删除的复制/移动构造函数

我想知道复制/移动省略何时适用(或允许应用)显式delete复制/移动构造函数和非delete复制/移动构造函数。以下是具体情况:

  1. 可以省略明确的deleted 复制 ctor 或移动 ctor 吗?delete是否允许通过跳过d 复制 ctor 和/或deleted 移动 ctor从另一个相同类型的对象或临时对象构造对象的尝试成功?

    这是 VC12 中发生的事情(我不确定是否有禁用复制/移动省略的选项):

    即使 IntelliSense 抱怨Foo{ Foo() };: Error: function “Foo::Foo(Foo &&)” ... cannot be referenced – it is a deleted function,编译器也不会抱怨,因此该行仍然可以编译。

  2. 为什么Foo{ Foo() };有效,但无效Foo{ std::move(f) };?如果一个电话忽略了移动 ctor,那么另一个电话不应该吗?

  3. 为什么Foo{ Foo() };有效,但无效Foo{ f };?这种选择性看起来很随意。这种右值引用优于 const 引用(反之亦然)的任意偏好似乎不适用于非 ctor 方法;在调用中,如果deleted 重载具有比非deleted 重载更高的重载决议优先级,则deleted 会阻塞非 d 重载,delete从而导致编译器错误:

    根据该逻辑,当参数不是临时参数时, a deletedFoo(Foo&&)不应阻止调用;将具有比在这种情况下更低的重载解决优先级。Foo(Foo const&)Foo(Foo&&)Foo(Foo const&)

  4. 我在 g++ 4.8 中尝试了相同的Foo示例,禁用复制省略(通过 flag -fno-elide-constructors)并再次启用它。两个 g++ 试验都给出了:

    error: use of deleted function 'Foo::Foo(Foo&&)'对于Foo{ Foo() };

    error: use of deleted function 'Foo::Foo(const Foo&)'为了Foo{ f };

    哪个编译器是正确的?

0 投票
1 回答
3218 浏览

c++ - GCC NRVO/RVO 警告

GCC中是否有任何警告可以让我们知道NRVO/RVO是否执行?

我发现-fno-elide-constructors关闭NRVO/RVO,但是NRVO/RVO有它自己的条件发生,有时不会发生。当额外的复制构造发生时,需要知道NRVO/RVO是否发生理解。

我对编译时特性特别感兴趣。如果有一些特定#pragma GCC...的(它会在其自身之后立即激活诊断)或使用静态断言机制的东西,那就太好了。

0 投票
2 回答
963 浏览

c++ - 按值返回时不调用复制构造函数

我在玩 C++ 构造函数。这是我的代码:

输出是:

前三行表示 foo() 函数中的局部变量是用构造函数创建的,并在 foo() 返回时销毁。第 4 行表示 b 是使用 move 构造函数构造的。但是,接下来的两行是最令人困惑的:我现在有一个新地址,它不同于 foo() 中的局部变量“a”,我曾经调用移动构造函数。当复制构造函数完成时,右值引用消失,析构函数被调用。但是为什么没有 0x7fff5d97bbc0 的复制构造函数呢?换句话说,0x7fff5d97bbc0 从何而来,又是如何构造的?很简单,调用的析构函数比调用的构造函数多一个。

我觉得这与复制省略有关。因此,我将 foo() 中的返回行更改为以下内容:

输出是:

现在终于明白了:在第三行,它表明复制构造函数在“a”被销毁之前被调用。这意味着,当按值返回时,它实际上是在销毁临时变量之前将值复制到返回值中。

但是我还是被原来的程序弄糊涂了(没有std::move()),因为如果真的是复制省略引起的,foo()的返回值的地址不应该和局部变量“a”一样吗? 现在它不同了,这意味着它在内存中的位置与“a”完全不同,那为什么不调用复制构造函数呢?

希望我的问题清晰易懂。

-------------------------------------------------- -----------------------------------------

编辑:我使用的编译器是带有 -fno-elide-constructors 标志的 clang++。

0 投票
1 回答
1159 浏览

c++ - 如何为特征向量启用复制省略移动成员?

对Eigen移动支持于 2011 年在此补丁中提交。但是我在 Matrix 头文件中找不到移动构造函数。此外,Eigen 网页仍然将移动语义列为“待办事项”项。这一切都表明补丁还没有提交到发布版本

这个测试程序证明了移动构造函数没有改变被移动的对象

输出是:

如何从Eigen 3.2.0 中的上述补丁中启用复制省略移动功能。?

编辑:

似乎 Eigen 类的移动语义没有任何问题。但是,只有默认的移动构造函数和移动赋值运算符。

提供显式移动构造函数和移动赋值运算符的补丁,可避免复制整个数据,但尚未合并到发布版本中。

我想知道:

  1. 如何将此补丁应用于 Eigen 3.2.0?是否有工具或者我应该手动修改文件。

  2. 有没有人有使用这个补丁的经验?

0 投票
1 回答
927 浏览

c++ - C++11 constructor argument: std::move and value or std::forward and rvalue reference

Which of the below two should be preferred and why?

vs

0 投票
3 回答
465 浏览

c++ - 传值导致额外移动

我试图理解移动语义和复制/移动省略。

我想要一个包含一些数据的类。我想在构造函数中传递数据并且我想拥有这些数据。

读完这个这个这个之后,我的印象是,在 C++11 中,如果我想存储一个副本,那么按值传递应该至少与任何其他选项一样有效(除了增加代码大小的小问题)。

然后,如果调用代码想避免复制,它可以通过传递一个右值而不是一个左值。(例如使用 std::move)

所以我试了一下:

输出:

我很高兴在这些情况下都没有调用复制构造函数,但为什么在第二种情况下调用了额外的移动构造函数?我想任何像样的移动构造函数Data都应该很快,但它仍然让我感到烦恼。我很想使用 pass-by-rvalue-reference (第一个选项),因为这似乎会导致更少的 move 构造函数调用,但如果可以的话,我想采用 pass-by-value 和复制省略。

0 投票
1 回答
414 浏览

c++ - 列表初始化和复制省略

考虑以下示例:

根据 8.5.16(C++11 标准)该行

被视为

(即创建了一个A 类型的临时对象并将其传递给A 类型的copy-ctor 来初始化一个x)。然后根据 12.8.31 编译器被允许(但不是强制)执行称为“复制省略”的优化,以消除创建 A 类型的临时代码,从而有效地使该行代码变为

(即没有创建临时对象,没有调用copy-ctors)。

现在,假设我在上面的示例中使用了列表初始化,如下所示:

或者

有人可以引用 C++11 标准中的适当段落来确认或否认 (1) 和/或 (2) 将始终(即不仅当编译器可以进行“复制省略”优化时)被视为

(即直接调用 A 的第一个构造函数,不创建临时对象,不复制 A 类型的对象)。

0 投票
1 回答
188 浏览

c++ - 复制省略和返回值优化与复制构造函数

我一直在阅读有关复制省略和返回值优化如何通过避免调用对象复制构造函数来提高速度的信息。我了解这些机制是如何工作的,但我想知道这是否会导致程序的行为与预期不同。

本质上,我的问题是;如果我们编写复制构造函数而不创建作为另一个对象副本的对象会发生什么?换句话说,如果

比如说,我们有一个这样的类:

这显然是一种可怕的行为,我并不是说我会做这样的事情。然而,重点是存在的;如果我们依赖副本的副作用怎么办?在此示例中,跟踪我们制作了多少副本。我希望优化不应该影响程序的运行方式。但是,复制省略可能会导致以下代码失败:

当我在没有优化的调试模式下构建时,这可能会返回 0,但是当我打开优化并且从 MakeAClass 的返回直接放在副本上时突然失败,跳过了复制构造函数。

当编译器尝试这些优化以寻找副作用时,是否有检查?当您要求副本时,期望代码执行副本是错误的吗?

0 投票
1 回答
834 浏览

c++ - RVO 和复制省略是否只能在一个编译单元内工作?

它们是否适用于不同的目标文件?它们是否跨不同的 DLL 工作?

我知道这取决于编译器。我很好奇是否有任何编译器和优化设置可以使这项工作。