提问人:OnionKing 提问时间:3/19/2023 最后编辑:OnionKing 更新时间:3/19/2023 访问量:87
C++ 编译器支持检测返回对临时对象的引用
C++ compiler support to detect returning a reference to a temporary object
问:
有一个截图代码,它返回对临时对象的引用:
#include <iostream>
#include <string>
const std::string& forward(const std::string& s)
{
return s;
}
int main()
{
const std::string& hello = forward("this is a random string with a reference to a temporary object");
std::cout << hello << "\n";
}
我编译了截图如下:
g++ -std=c++20 -Wpedantic -Wall test.cpp -o test
clang++ -std=c++20 -Wpedantic -Wall test.cpp -o test
我预计会收到一条警告消息,但没有关于“forward()”函数的这种错误使用的警告。warning: returning reference to temporary
是否有任何 C++ 编译器支持在返回临时对象时检测此类情况?
答:
函数本身或对它的调用没有问题。返回时,临时对象仍处于活动状态。它的生存期仅在初始化 后结束。因此,警告说该函数返回一个悬空引用是不正确的。函数调用的结果仍然可以在同一个完整表达式中使用,而不会出现任何悬空。forward
hello
只有在初始化后,您才会遇到问题,当立即变得悬空时。然后使用有UB。hello
hello
std::cout << hello << "\n";
要识别 的初始化会导致在输出语句后面访问悬空指针,编译器至少需要内联 .因此,如果编译器的分析只能在启用优化的情况下检测到此问题,也就不足为奇了。hello
forward
GCC 12 及更高版本似乎正是这种情况,它会在启用优化(至少 )和 .Clang 和 MSVC 目前似乎没有执行这样的分析。-O1
-Wall
但是,我希望像 clang-analyze 这样的静态分析器以及像 ASAN(用于 GCC/Clang)这样的运行时清理器能够检测到这个问题(在我的测试中,ASAN 在任何优化级别上都对 GCC 和 Clang 都如此)。-fsanitize=address
评论
forward
可以接受 rvalues 和 lValues。编译器必须对调用进行完整跟踪,以处理每次调用中传递的内容。如果更改为 是否收到错误?forward
const std::string& forward(const std::string && s)
-O -Wall
const std::string && s
-O -Wall
forward
仅当使用临时参数调用它时,才是一个潜在问题。就其本身而言,没有理由发出任何警告。