Ori*_*ent 19 c++ gcc g++ copy-elision
是否有任何警告,让我们知道在海湾合作委员会中是否进行了NRVO/RVO?
我发现-fno-elide-constructors关闭NRVO/RVO,但NRVO/RVO有自己的条件发生,有时不会发生.当需要额外的复制构造时,需要知道是否发生了NRVO/RVO.
我对编译时功能特别感兴趣.如果有一些特定的#pragma GCC...(它会立即激活诊断)或使用静态断言机制的东西会很好.
我不知道任何gcc特定的诊断消息或其他方法可以轻松解决您的任务。如您-fno-elide-constructors所知,它将禁用复制/移动省略,因此您将确定至少在这种情况下不会发生(N)RVO。
但是,快速浏览此C ++ 11工作草案的 12.8节中的第31段时会指出:
当满足某些条件时,即使该对象的复制/移动构造函数和/或析构函数具有副作用,也允许实现忽略类对象的复制/移动构造。在这种情况下,实现将忽略的复制/移动操作的源和目标视为引用同一对象的两种不同方式,并且该对象的销毁发生在两个对象本来应该以较晚的时间发生。没有优化就销毁。在以下情况下允许复制/移动操作的这种省略(称为复制删除)(可以合并以消除多个副本):
- 在具有类返回类型的函数的return语句中,当表达式是具有与函数返回类型相同的cv不合格类型的非易失性自动对象(函数或catch子句参数除外)的名称时,通过将自动对象直接构造到函数的返回值中,可以省略复制/移动操作
...
- 当尚未绑定到引用(12.2)的临时类对象将被复制/移动到具有相同cv-unqualified类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制/移动操作省略的副本/移动的
...
发生复制/移动省略时,本地自动对象与临时(返回)对象相同,而临时(返回)对象又与“存储”对象(存储返回值)相同。因此,本地自动对象与存储对象相同,这意味着指针比较将等于true。一个简单的例子来证明这一点:
#include <iostream>
#include <vector>
std::vector<int> testNRVO(int value, size_t size, const std::vector<int> **localVec)
{
std::vector<int> vec(size, value);
*localVec = &vec;
/* Do something here.. */
return vec;
}
int main()
{
const std::vector<int> *localVec = nullptr;
std::vector<int> vec = testNRVO(0, 10, &localVec);
if (&vec == localVec)
std::cout << "NRVO was applied" << std::endl;
else
std::cout << "NRVO was not applied" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
启用/禁用-fno-elide-constructors按预期更改打印的消息。注意:从严格意义上讲,当不发生(N)RVO时,指针比较可能取决于未定义的行为,因为本地自动对象不存在。
进行指针比较会增加麻烦,但是具有编译器独立性的优点。
小智 3
GCC 中是否有任何警告可以让我们知道 NRVO/RVO 是否执行?
gcc (trunk)(尚未发布 v14)有-Wnrvo
“如果编译器没有在 [class.copy.elision] 允许的上下文中删除从局部变量到函数返回值的复制,则会发出警告。这种删除通常称为命名返回值优化。”
gcc (trunk)可以在https://godbolt.org/上找到