问题标签 [nrvo]

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 投票
1 回答
274 浏览

c++ - NRVO 不应该保证本地命名变量和调用站点变量采用相同的地址吗?

我认为它应该,因为它对正确性很重要。但是,我很惊讶地看到 Clang 的输出。考虑下面的代码:

我们定义了一个 move ctorS来检查是否S(S&&)被调用,如果没有,则应用 NRVO。

我们从 GCC 看到的结果是:

应用了 NRVO,它们采用相同的地址,这是预期的。

但是,Clang 的输出

应用了 NRVO,但地址不同。

如果您想知道为什么拥有相同的地址很重要 - 这是因为某些对象可能会在构造时对其地址进行一些注册,并且如果对象被移动,则应该通知它(例如通过 move-ctor)。

应用了 NRVO 但具有不同的内存地址因此使其格式错误。这明显违反了合同 - 没有调用自定义移动/复制 ctor,编译器如何将 S 的数据“复制”到不同的地方?

这是 Clang 中的错误吗?


如果我们添加一个析构函数S,例如

这一次,Clang 输出相同的地址。

0 投票
1 回答
927 浏览

c++ - C++:我应该在 return 语句中明确使用 std::move() 来强制移动吗?

编辑:它不是重复的,因为这个问题询问编译器在 O0 中的决定。

这里说名称返回值优化(NRVO)是许多编译器支持的优化。但它是必须的还是只是一个不错的优化?

我的情况是,为了方便调试,我想编译-O0(即没有优化),但我也希望为返回对象(比如向量)的返回语句启用 NRVO。如果 NRVO 不是必须的,编译器可能不会在-O0模式下执行此操作。在这种情况下,我应该更喜欢这段代码:

在下面这个?

编辑:我使用的编译器是 GCC6,但我希望代码独立于编译器。

0 投票
1 回答
60 浏览

c++ - 实现与 decalation 分离的库能否从 RVO/NRVO 中受益?

正如标题所示,我正在编写一个带有类模板和几个非模板运算符重载的静态库。类模板在ah中定义,函数在a.cc中定义。

所以我决定继续问 RVO/NRVO 是否可以使库的用户代码受益?

编辑:对此我很抱歉,这是我刚刚问的另一个问题,不应该放在这个问题中。为了让场景更清晰,我实际上是在尝试封装 uint8_t 等类型,并计划自己编写一些大型整数类型。

0 投票
1 回答
72 浏览

c++ - 成员访问的 C++ 副本

我正在做一些实验,看看除了复制省略、RVO、NRVO 案例之外何时执行复制。

所以我写了一些这样的代码:

我收到以下输出:

使用 gcc 编译或使用 -O3 编译并尝试 -std=c++{11,14,17} 都产生相同的输出。

令我惊讶的是,我没想到使用 y.getX(); 时会执行任何复制;到一个 const 变量。这是我经常使用的东西,只是为了简化我在以下代码中对该变量及其成员的访问,但我并没有通过 const 引用执行它,而是我只是使用 const 希望编译器将它视为重命名。

有谁知道为什么要执行该副本?我想到的唯一原因是它使代码线程安全。如果有多个线程处理对象 y,那么我对 const 的分配毕竟不会是那个 const。因为它只会引用对象 y 中的成员 x。这可能会被其他线程更改。但我不确定这是否是真正的意图。

0 投票
3 回答
1668 浏览

c++ - 我可以依靠命名返回值优化复杂的返回类型吗?

考虑这样的事情:

这种方法对于生成子集、排列等问题是相当标准的。但是,我尝试制作一个图表,说明返回值优化应该在这里优化什么,因为该类型的内部数据结构相当复杂(std::unordered_multiset是一个哈希表,并且std::set“通常' 一个二叉搜索树),好吧,我只能希望编译器比我更聪明。

那么,谈论性能和(如果重要的话)C++14,我可以在这里返回一个SetOfSets还是应该通过引用将它作为输出参数传递?

0 投票
2 回答
798 浏览

c++ - C ++ nrvo/复制省略,括号中带有return语句

我在玩弄下面的代码,使用我的 Visual Studio 2017 应用程序和两个不同的在线编译器得到了不同的结果。在发布模式下,Visual Studio 确实在这两种情况下都省略了复制/移动,而两个在线编译器只是在没有括号的 return 语句的情况下这样做。我的问题是:谁是对的,更重要的是,基本规则是什么。(我知道您可以将括号与decltype(auto)语法结合使用。但这不是当前的用例)。

示例代码:

在线编译器1: http ://cpp.sh/75bux

在线编译器 2: http ://coliru.stacked-crooked.com/a/c266852b9e1712f3

Visual Studio 在发布模式下的输出是:

在另外两个编译器中,输出为:

0 投票
1 回答
755 浏览

c++ - C++ ABI 如何处理 RVO 和 NRVO?

我对编译器和链接器如何处理函数调用者的要求根据函数是使用 RVO 还是 NRVO 而不同这一事实感到困惑。

这可能是我的误解,但我的假设是通常没有 RVO 或 NRVO

如果 get_string 不执行 N?RVO 但如果 get_string 执行 N?RVO 调用代码不执行任何操作s并由函数 get_string 就地构造,则涉及从 get_string 的结果移动构造 s。

编辑:如果没有 N?RVO,这就是我想象的 get_string 调用者的操作方式:

  1. 调用 get_string()
  2. get_string 结果现在在堆栈上,调用者使用它来构造 s

现在有了 RVO

  1. 调用 get_string()
  2. 当 get_string 完成后,栈上没有结果,get_string 构造了 s,调用者不需要做任何事情来构造 s。
0 投票
1 回答
443 浏览

c++ - 如果我们有 (N)RVO,什么时候实际调用移动构造函数?

我从关于 SO 的几个问题中了解到,当对象按值返回时,(N)RVO 会阻止调用移动构造函数。经典例子:

启用 (N)RVO 的输出为:

那么在什么情况下会调用移动构造函数,而不管 (N)RVO 是否存在?你能提供一些例子吗?换句话说:如果 (N)RVO 默认执行其优化工作,我为什么要关心实现移动构造函数?

0 投票
1 回答
85 浏览

c++ - 在存在错误代码的情况下输出参数与 NRVO

我们有一个广泛使用参数的代码库,因为每个函数都可能因一些错误枚举而失败。这变得非常混乱,代码有时不可读。

我想消除这种模式并带来更现代的方法。

目标是改造:

变成类似的东西:

以下问题是为了让我自己和其他人相信这种改变是最好的:

  1. 我知道在标准级别上,NRVO 不是强制性的(与 c++17 中的 RVO 不同),但实际上有没有可能在任何主要编译器中都不会发生?
  2. 使用 out 参数代替 NRVO 有什么好处吗?
  3. 假设 NRVO 发生,生成的程序集是否有显着变化(假设一个优化的expected实现 [也许用布尔值表示是否发生错误完全消失])?
0 投票
1 回答
632 浏览

c++ - 编译器是否足够聪明地 std::move 变量超出范围?

考虑以下代码:

return v是 O(1),因为 NRVO 将省略复制,v 直接在存储中构造函数的返回值,否则函数的返回值将被移动或复制到. 现在考虑功能类似的代码:

可以在这里提出一个类似的论点,*to_be_filled = v可以想象它可以编译为 O(1) 移动分配,因为它是一个超出范围的局部变量(编译器应该很容易验证其中v没有外部引用这种情况,因此在最后一次使用时将其提升为右值)。是这样吗?有一个微妙的原因吗?

此外,感觉这种模式可以扩展到左值超出范围的任何上下文:

期望编译器找到诸如 the 之类的模式*to_be_filled = v,然后自动优化它们以假设右值语义,是否/可以/是否有用/合理?


编辑:

g++ 7.3.0在 -O3 模式下不执行任何此类优化。