Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 我有一种感觉。但我怎么能确定呢?_C++_Undefined Behavior - Fatal编程技术网

C++ 我有一种感觉。但我怎么能确定呢?

C++ 我有一种感觉。但我怎么能确定呢?,c++,undefined-behavior,C++,Undefined Behavior,给定下面的代码,编译器为函数f1()和f2()发出警告C4172:返回局部变量或临时,但不为f3()。我理解编译器在某些情况下可能无法识别此问题,因为下面的函数f3()就是这种情况。但是,在没有警告信息的情况下,我如何确定这种情况下的正确诊断 const char* const& f1() { return "hello1"; } const char* const& f2() { return static_cast<const char*>("hello2");

给定下面的代码,编译器为函数f1()和f2()发出
警告C4172:返回局部变量或临时
,但不为f3()。我理解编译器在某些情况下可能无法识别此问题,因为下面的函数f3()就是这种情况。但是,在没有警告信息的情况下,我如何确定这种情况下的正确诊断

const char* const& f1() { return "hello1"; }
const char* const& f2() { return static_cast<const char*>("hello2"); }
const char* const& f3() { const char* const& r = "hello3"; return r; }
const char*const&f1(){返回“hello1”;}
const char*const&f2(){return static_cast(“hello2”);}
const char*const&f3(){const char*const&r=“hello3”;返回r;}

是,代码的行为未定义,因为它返回对本地指针的引用,而本地指针在
f1
f2
中被正确检测到

您不能依赖编译器的诊断来捕获这些(或任何其他)未定义行为的情况,它们是在“尽力而为”的基础上提供的。在这个简单的例子中,g++4.8.0不警告(使用
-Wall
)显示编译器很容易被愚弄:

int& r() {
    int x = 1;
    int& y = x;
    return y;
}

(仅返回
x
按预期发出警告,并且
clang
对所有四个函数发出警告。)

是的,代码的行为未定义,因为它返回对本地指针的引用,而本地指针在
f1
f2
中被正确检测到

您不能依赖编译器的诊断来捕获这些(或任何其他)未定义行为的情况,它们是在“尽力而为”的基础上提供的。在这个简单的例子中,g++4.8.0不警告(使用
-Wall
)显示编译器很容易被愚弄:

int& r() {
    int x = 1;
    int& y = x;
    return y;
}

(只需按预期返回
x
警告,以及
clang
对所有四个函数发出警告。)

我确信所有三个函数都有未定义的行为

对于坚持认为
f3
不是UB(甚至
f1
/
f2
)的人:请尝试运行此代码:

#include <iostream>

const char* const& f1() { return "hello1"; }
const char* const& f2() { return static_cast<const char*>("hello2"); }
const char* const& f3() { const char* const& r = "hello3"; return r; }

int main()
{
    using namespace std;

//#define F f1
//#define F f2
#define F f3

    const char* const& ret = F();
    cerr << ret;
    cerr << ",";
    cerr << ret;

    return 0;
}
实际上,字符串literal
“hello3”
不是一个
常量字符*
,而是一个(静态)
常量字符[7]
。在代码中
const char*const&r=“hello3”,引用不能直接绑定到此字符数组,因为它的类型不同,因此编译器必须创建一个临时字符指针(在堆栈上创建),该指针通过隐式转换(数组到指针衰减)初始化,引用绑定到该指针()。此临时
const char*
的生存期被“扩展”到引用
r
的生存期,因此不会在第一个分号处结束,而是在函数返回(和)时结束。因此,
f3
返回一个“悬挂引用”。在我的测试输出代码中,任何覆盖堆栈的后续操作都会使UB可见


在jalf的评论之后编辑:我意识到“它在第二次输出上打印垃圾”并不是UB的证据。带有UB的程序可以完全按照预期工作,或者崩溃,或者什么都不做,或者其他任何事情。但是,尽管如此,我不相信一个定义良好的程序(没有UB)会像那样打印垃圾…

我确信这三个函数都有未定义的行为

对于坚持认为
f3
不是UB(甚至
f1
/
f2
)的人:请尝试运行此代码:

#include <iostream>

const char* const& f1() { return "hello1"; }
const char* const& f2() { return static_cast<const char*>("hello2"); }
const char* const& f3() { const char* const& r = "hello3"; return r; }

int main()
{
    using namespace std;

//#define F f1
//#define F f2
#define F f3

    const char* const& ret = F();
    cerr << ret;
    cerr << ",";
    cerr << ret;

    return 0;
}
实际上,字符串literal
“hello3”
不是一个
常量字符*
,而是一个(静态)
常量字符[7]
。在代码中
const char*const&r=“hello3”,引用不能直接绑定到此字符数组,因为它的类型不同,因此编译器必须创建一个临时字符指针(在堆栈上创建),该指针通过隐式转换(数组到指针衰减)初始化,引用绑定到该指针()。此临时
const char*
的生存期被“扩展”到引用
r
的生存期,因此不会在第一个分号处结束,而是在函数返回(和)时结束。因此,
f3
返回一个“悬挂引用”。在我的测试输出代码中,任何覆盖堆栈的后续操作都会使UB可见


在jalf的评论之后编辑:我意识到“它在第二次输出上打印垃圾”并不是UB的证据。带有UB的程序可以完全按照预期工作,或者崩溃,或者什么都不做,或者其他任何事情。但是,尽管如此,我不相信一个定义良好的程序(没有UB)会像那样打印垃圾…

您使用的是哪种编译器(和版本)?我已经在VS2010和GCC中对此进行了测试,(它们一直存在到程序结束)没有一个函数有UB。实现需要为这些情况提供诊断,幸运的是它们提供了诊断,但您不能盲目相信这些诊断。@CaptainObvlious我刚刚意识到这些函数不会返回
常量字符*
,而是返回
常量字符*常量&
,也就是说,指向静态字符数组的指针不是通过值返回的,而是通过引用const!因此,提出了正确的警告<代码> f3是相同的,但是使用显式命名变量似乎欺骗了编译器在标题中的问题,唯一的方法是确定是否是UB,是通过在ISO C++标准中查找的。如果您可以在那里找到一段描述代码行为的文字,那么它是定义良好的。如果没有这样的段落存在(或者如果你发现有一段明确地说它是未定义的),那么它就是UB。遗憾的是,没有简单的快捷方式(尽管在这里询问可能会提示响应,告诉您在标准中查找的位置)您使用的是哪种编译器(和版本)?我已经在VS2010和GCC中测试过这一点,(它们在程序结束前都是活动的)所有函数都没有UB。实现需要为这些情况提供诊断,幸运的是它们确实提供了诊断,但您不能盲目相信这些诊断。@CaptainObvlious我刚刚意识到这些函数不会返回
const char*