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

c++ - 将结构像 std::list> 返回时被复制?

我有一个函数,可以从给定的字符串中提取键值列表,其中每个键/值对由 a 表示std::pair,该函数具有如下签名:

如果我的实现看起来像:

1) 我不希望发生任何副本,我想知道 RVO/NRVO 是否会应用于列表中的对和持有它们的列表。

2)如果在这种情况下会发生复制,那么在不复制的情况下实现这一点的替代数据结构是什么?我可以想到一个使用 的解决方案unique_ptr<unorder_map<>>,但就我而言,我只需要支持列表中对的迭代,不需要支持通过它们的键查找值,因此我想避免在插入过程中进行不必要的哈希计算。

3) 我知道 RVO/NRVO 是依赖于编译器的行为,有什么方法可以验证这些行为是否容易发生?

0 投票
2 回答
364 浏览

c++ - 如果没有定义析构函数,为什么不会发生返回值优化?

我希望从这个测试程序中看到来自命名返回值优化 (NRVO) 的复制省略,但它的输出是“地址不匹配!” 所以 NRVO 没有发生。为什么是这样?

笔记:

  1. 如果通过启用#if上述方法定义了析构函数,则 NRVO 确实会发生(并且在其他一些情况下也会发生,例如定义虚拟方法或添加std::string成员)。

  2. 没有定义任何方法,所以 A 是一个 POD 结构,或者在最近的术语中是一个琐碎的 class。我在上面的链接中没有看到明确的排除。

  3. 添加编译器优化(添加到一个更复杂的示例,而不仅仅是简化为空程序!)没有任何区别。

  4. 查看第二个示例的程序集表明,当我期望强制返回值优化 (RVO) 时,甚至会发生这种情况,因此上面的 NRVO 并没有通过获取 in 的地址来fn_a阻止fn()。x86-64 上的 Clang、GCC、ICC 和 MSVC 显示相同的行为,表明此行为是故意的,而不是特定编译器中的错误。

0 投票
1 回答
63 浏览

c++ - 如果一个变量被分配了一个函数返回的对象,它是复制还是就地创建?

我的 CPP 文件中有类似的东西来初始化任何类之外的对象。我已经简化了它,但关键是正在进行一些复杂的初始化,但我想要创建一个实例:

ret我的问题是,由于编译器的聪明,这个对象是否被复制o或就地创建?“就地创造”可能有一个恰当的术语——安置?

如果相关的话,我正在使用 C++17(即答案取决于语言版本)。是否有明确的答案,或者这可能是特定于编译器的优化?

0 投票
0 回答
74 浏览

c++ - 为什么这里不执行 NRVO(多次返回)?

MyString ret在以下方法中不执行 NRVO 。默认构造的 MyString ( return {};) 直接构造到目标中, ret 被移动构造到目标中。

如果在其主体中MyString ret{length + 1};的 if 语句之上return{};,我会很清楚为什么它不能直接构造到目标中:如果是,则返回默认构造的 MyString 对象,销毁ret将是必需的,并且默认构造的对象将取代它。这是不可取的。但是,在这种情况下,MyString ret不能直接构造到目标中的根本原因是什么?在代码中构造时,众所周知该函数不会return {};.

我确定我在这里忽略了一些东西。任何帮助是极大的赞赏!

编辑:这是@rustyx 建议的最小可重复示例:

这打印:

0 投票
2 回答
61 浏览

c++ - 我可以在返回多个值时避免复制,同时保持我的返回类型吗?

如果我们编写如下函数:

然后NRVO应该启动,这样foo就不会在返回时被复制。

现在假设我想返回两个不同的值:

Foo这种幼稚的实现可能会触发每个和Bar( GodBolt)的两个副本的构造。

我应该如何最好地修改我的代码以避免这种复制,而不会弄乱我的返回类型?

0 投票
1 回答
55 浏览

c++ - 可以在调试版本中关闭 NRVO 吗?

在程序中如下

我希望命名返回值优化发生在 foo() 中,因此不会调用复制或移动构造函数。确实 gcc 和 clang 打印“0”。

但是调试配置中的 Visual Studio 2019 打印“02”。是否允许编译器在调试版本中避免使用 NRVO?

0 投票
1 回答
78 浏览

c++ - RVO 是预期的,但没有发生

我有以下连接池的基本实现。在非常高的级别上,它为客户端提供了一种从池中获取打开连接的安全方式,或者如果所有连接当前都在使用中,则打开一个新连接。结构是连接的Connection低级实现。ClientConnectionstruct 是一个包装器,因此Connection客户端只能有限地访问对象,并为使用 RAII 将对象返回到池中Connection提供一种安全的方式。Connection打电话时Pool::getNewConnection(),我预计 NRVO 会发生,但它没有发生,我终生无法弄清楚原因。我希望只调用一次析构函数,因为我创建了ClientConnectioninmain()然后它被销毁了。但是,发生的情况是在Pool::getNewConnection(),然后移动到对象的内存中main(),因此调用了2个析构函数。

g++ -std=c++17 -O0 -g -o main main2.cpp使用和构建g++ -std=c++17 -O3 -g -o main main2.cpp

输出是:

0 投票
2 回答
50 浏览

c++ - 返回一对对象

下面是一个反模式:

使用 astd::move甚至会产生最差的代码(见这里

但是,在以下情况下我应该怎么做: