我正在回答一个问题并建议为大型类型返回按值,因为我相信编译器会执行返回值优化(RVO).但后来有人向我指出Visual Studio 2013没有在我的代码上执行RVO.
我在这里发现了一个关于Visual Studio无法执行RVO的问题,但在这种情况下,结论似乎是,如果真的很重要Visual Studio将执行RVO.在我的情况下它确实很重要,它对性能产生了重大影响,我已经通过分析结果证实了这一点.这是简化的代码:
#include <vector>
#include <numeric>
#include <iostream>
struct Foo {
std::vector<double> v;
Foo(std::vector<double> _v) : v(std::move(_v)) {}
};
Foo getBigFoo() {
std::vector<double> v(1000000);
std::iota(v.begin(), v.end(), 0); // Fill vector with non-trivial data
return Foo(std::move(v)); // Expecting RVO to happen here.
}
int main() {
std::cout << "Press any key to start test...";
std::cin.ignore();
for (int i = 0; i != 100; ++i) { …Run Code Online (Sandbox Code Playgroud) 这是从Efficient方式返回c ++中的std :: vector的扩展问题
#include <cstdio>
#include <vector>
#include <chrono>
std::vector<int> func1() {
std::vector<int> v;
v.reserve(1e6);
for (int i = 0; i < 1e6; i++) v.emplace_back(i);
return v;
}
std::vector<int> func2() {
std::vector<int> v;
v.reserve(1e6);
for (int i = 0; i < 1e6; i++) v.emplace_back(i);
return std::move(v);
}
int main() {
auto start1 = std::chrono::steady_clock::now();
std::vector<int> v1 = func1();
auto end1 = std::chrono::steady_clock::now();
printf("%d\n", std::chrono::duration_cast<std::chrono::nanoseconds>(end1-start1).count());
auto start2 = std::chrono::steady_clock::now();
std::vector<int> v2 = func2();
auto end2 = std::chrono::steady_clock::now();
printf("%d\n", …Run Code Online (Sandbox Code Playgroud) 在许多情况下,我想创建一个新的数据实例并将其返回给 API 调用方。
我了解到unique_ptr/shared_ptr可用于工厂模式(例如,在 C++ 中使用 unique_ptr 的工厂模式)
同时,我了解到在许多编译器中都可以进行返回值优化 (RVO)(例如,在 c++ 中返回 std::vector 的有效方法)。
我更喜欢 RVO 因为它更容易使用没有包装的返回值unique_ptr并且更容易阅读代码,但是,由于不能保证 RVO,所以我不想意外牺牲性能并且必须使用unique_ptr以确保返回值是moved而不是复制。
是否有任何方法可以明确指定要移动的返回值,以便在 RVO 可能的情况下它不会抱怨任何内容,或者如果 RVO 不可能,它将触发一些编译器警告?如果这是可能的,我可以安全地摆脱在这种情况下返回 unique_ptr 的情况。
我使用的是 C++17,需要在 macOS 上支持 Apple Clang 11.0,在 Linux 上支持 g++ 9。
编辑:
我仍在学习 C++ 并且在发布此问题时没有区分 RVO(返回值优化)和 NRVO(命名返回值优化)。在我看来 NRVO 在像工厂方法这样的模式中更常见和有用,例如:
vector<foo> vec;
// populate data into vec
return vec;
Run Code Online (Sandbox Code Playgroud)
我正在寻找类似 a 的东西return std::move_only(returned_value),如果无法移动该值(而不是复制移动),它将给我一个编译器警告。也许我应该重新表述我的问题:如果不能保证 NRVO,为什么“按值返回”仍然是这个问题中的推荐方式(在 c++ 中返回 std::vector 的有效方法),答案不应该是“这取决于”您的功能实现以及您是否可以接受意外的性能成本?