c++ - 不知道某些东西是否被省略会引入未定义的行为吗?

标签 c++ undefined-behavior copy-elision

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

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();}
保证做复制省略,所以如果 ex 上面的代码没问题是 f1() 的结果.
一般来说,我建议不要依赖于此,只需为您的类提供正确的复制构造函数即可避免此类问题。

关于c++ - 不知道某些东西是否被省略会引入未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62840020/

相关文章:

rust - 别名可变原始指针 (*mut T) 会导致未定义的行为吗?

c++ - 返回具有已删除移动/复制构造函数的临时类型

c++ - 意外的复制构造函数

C++使用多个定界符分解字符串

javascript - 将值从 C++ 传递到 Javascript

c - 为什么这些构造使用增量前和增量后未定义的行为?

c++ - 为什么简单地取消引用分配了 NULL 的指针不会崩溃

c++ - 如何为 C++ 映射创建自己的字符串比较对象

c++ - QtQuick 使用 QQuickTextNode

c++ - 将参数省略复制为返回值