考虑这样的事情:
typedef std::unordered_multiset<int> Set;
typedef std::set<Set> SetOfSets;
SetOfSets somethingRecursive(SomeType somethingToAnalyze) {
Set s;
// ...
// check base cases, reduce somethingToAnalyze, fill in s
// ...
SetOfSets ss = somethingRecursive(somethingToAnalyze);
ss.insert(s);
return ss;
}
Run Code Online (Sandbox Code Playgroud)
这种方法对于生成子集、排列等问题来说是相当标准的。 但是,我尝试制作一个图表,说明返回值优化应该在这里优化什么,因为该类型的内部数据结构相当复杂(std::unordered_multiset是一个哈希表,并且std::set通常是' 一个二叉搜索树),好吧,我只能希望编译器比我更聪明。
那么,谈论性能和(如果重要的话)C++14,我可以在SetOfSets这里返回 a还是应该通过引用将它作为输出参数传递?
在 C++17 之前,您根本不能依赖复制省略,因为它是可选的。然而,所有主流编译器很可能会应用它(例如,GCC 即使使用-O0优化标志也会应用它,-fno-elide-constructors如果你愿意,你需要明确地禁用复制省略)。
但是,std::set支持移动语义,因此即使没有 NRVO,您的代码也没有问题。
请注意,在 C++17 中,NRVO 也是可选的。RVO 是强制性的。
从技术上讲,IMO,C++17 中没有 RVO,因为当返回 prvalue 时,没有临时物化可以从中移动/复制。规则有点不同,但效果或多或少是一样的。或者,甚至更强,因为在 C++17 中不需要复制/移动构造函数按值返回纯右值:
#include <atomic>
std::atomic<int> f() {
return std::atomic<int>{0};
}
int main() {
std::atomic<int> i = f();
}
Run Code Online (Sandbox Code Playgroud)
在 C++14 中,此代码无法编译。