不知道某个东西是否被忽略会引入未定义的行为吗

Can not knowing whether something is elided introduce undefined behavior?

本文关键字:未定义 是否 不知道      更新时间:2023-10-16

假设我们有一个结构,它有一个成员指针,该指针有条件地指向内部数组或堆上的某个位置,如下所示:

struct Ex {
char* p;
char data[14];
bool is_heap;
Ex() : p(&data[0]), data(), is_heap(false) {}
//etc...
};

现在考虑这个函数

Ex f1() {return Ex();}

由于复制省略,下面的代码将打印出";h":

int main() {
auto ex = f1();
ex.data[0] = 'h';
std::cout << ex.p[0];
}

但是,考虑以下函数

Ex f2() {
auto ret = Ex();
return ret;
}

据我所知,这个函数可能被删除,但如果不是,以下代码将是未定义的行为:

int main() {
auto ex = f2();
ex.data[0] = 'h';
std::cout << ex.p[0]; // maybe derefrencing dangling pointer, maybe printing out "h"?
}

我的问题是,示例2总是未定义的行为吗?它是否是未定义的行为(比如它是否决定消除(取决于编译器吗?还是定义明确的行为?(同样的问题也可能适用于第一个例子(

在所有不强制执行复制省略的情况下,执行以下操作时会出现未定义的行为:

auto ex = ... 
ex.data[0] = 'h';
std::cout << ex.p[0]; 

从c++17开始,此函数:

Ex f1() {return Ex();}

保证执行复制省略,因此如果exf1()的结果,则上面的代码是可以的。

一般来说,我建议不要依赖于此,只需为类提供正确的复制构造函数即可避免此类问题。