问题标签 [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.
c++ - NRVO 不应该保证本地命名变量和调用站点变量采用相同的地址吗?
我认为它应该,因为它对正确性很重要。但是,我很惊讶地看到 Clang 的输出。考虑下面的代码:
我们定义了一个 move ctorS
来检查是否S(S&&)
被调用,如果没有,则应用 NRVO。
我们从 GCC 看到的结果是:
应用了 NRVO,它们采用相同的地址,这是预期的。
但是,Clang 的输出:
应用了 NRVO,但地址不同。
如果您想知道为什么拥有相同的地址很重要 - 这是因为某些对象可能会在构造时对其地址进行一些注册,并且如果对象被移动,则应该通知它(例如通过 move-ctor)。
应用了 NRVO 但具有不同的内存地址因此使其格式错误。这明显违反了合同 - 没有调用自定义移动/复制 ctor,编译器如何将 S 的数据“复制”到不同的地方?
这是 Clang 中的错误吗?
如果我们添加一个析构函数S
,例如
这一次,Clang 输出相同的地址。
c++ - C++:我应该在 return 语句中明确使用 std::move() 来强制移动吗?
编辑:它不是重复的,因为这个问题询问编译器在 O0 中的决定。
这里说名称返回值优化(NRVO)是许多编译器支持的优化。但它是必须的还是只是一个不错的优化?
我的情况是,为了方便调试,我想编译-O0
(即没有优化),但我也希望为返回对象(比如向量)的返回语句启用 NRVO。如果 NRVO 不是必须的,编译器可能不会在-O0
模式下执行此操作。在这种情况下,我应该更喜欢这段代码:
在下面这个?
编辑:我使用的编译器是 GCC6,但我希望代码独立于编译器。
c++ - 实现与 decalation 分离的库能否从 RVO/NRVO 中受益?
正如标题所示,我正在编写一个带有类模板和几个非模板运算符重载的静态库。类模板在ah中定义,函数在a.cc中定义。
所以我决定继续问 RVO/NRVO 是否可以使库的用户代码受益?
编辑:对此我很抱歉,这是我刚刚问的另一个问题,不应该放在这个问题中。为了让场景更清晰,我实际上是在尝试封装 uint8_t 等类型,并计划自己编写一些大型整数类型。
c++ - 成员访问的 C++ 副本
我正在做一些实验,看看除了复制省略、RVO、NRVO 案例之外何时执行复制。
所以我写了一些这样的代码:
我收到以下输出:
使用 gcc 编译或使用 -O3 编译并尝试 -std=c++{11,14,17} 都产生相同的输出。
令我惊讶的是,我没想到使用 y.getX(); 时会执行任何复制;到一个 const 变量。这是我经常使用的东西,只是为了简化我在以下代码中对该变量及其成员的访问,但我并没有通过 const 引用执行它,而是我只是使用 const 希望编译器将它视为重命名。
有谁知道为什么要执行该副本?我想到的唯一原因是它使代码线程安全。如果有多个线程处理对象 y,那么我对 const 的分配毕竟不会是那个 const。因为它只会引用对象 y 中的成员 x。这可能会被其他线程更改。但我不确定这是否是真正的意图。
c++ - 我可以依靠命名返回值优化复杂的返回类型吗?
考虑这样的事情:
这种方法对于生成子集、排列等问题是相当标准的。但是,我尝试制作一个图表,说明返回值优化应该在这里优化什么,因为该类型的内部数据结构相当复杂(std::unordered_multiset
是一个哈希表,并且std::set
“通常' 一个二叉搜索树),好吧,我只能希望编译器比我更聪明。
那么,谈论性能和(如果重要的话)C++14
,我可以在这里返回一个SetOfSets
还是应该通过引用将它作为输出参数传递?
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 在发布模式下的输出是:
在另外两个编译器中,输出为:
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 调用者的操作方式:
- 调用 get_string()
- get_string 结果现在在堆栈上,调用者使用它来构造 s
现在有了 RVO
- 调用 get_string()
- 当 get_string 完成后,栈上没有结果,get_string 构造了 s,调用者不需要做任何事情来构造 s。
c++ - 如果我们有 (N)RVO,什么时候实际调用移动构造函数?
我从关于 SO 的几个问题中了解到,当对象按值返回时,(N)RVO 会阻止调用移动构造函数。经典例子:
启用 (N)RVO 的输出为:
那么在什么情况下会调用移动构造函数,而不管 (N)RVO 是否存在?你能提供一些例子吗?换句话说:如果 (N)RVO 默认执行其优化工作,我为什么要关心实现移动构造函数?
c++ - 在存在错误代码的情况下输出参数与 NRVO
我们有一个广泛使用参数的代码库,因为每个函数都可能因一些错误枚举而失败。这变得非常混乱,代码有时不可读。
我想消除这种模式并带来更现代的方法。
目标是改造:
变成类似的东西:
以下问题是为了让我自己和其他人相信这种改变是最好的:
- 我知道在标准级别上,NRVO 不是强制性的(与 c++17 中的 RVO 不同),但实际上有没有可能在任何主要编译器中都不会发生?
- 使用 out 参数代替 NRVO 有什么好处吗?
- 假设 NRVO 发生,生成的程序集是否有显着变化(假设一个优化的
expected
实现 [也许用布尔值表示是否发生错误完全消失])?
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 模式下不执行任何此类优化。