You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++17前后对象返回时指针行为与复制消除的技术咨询

C++17前后函数返回对象的内部指针行为与复制消除关联问题

先看代码示例:

struct A {
    void* p;
    A() : p(this) {}
    A(const A&); // 禁用平凡可复制性
};

A f() {
    A x;
    return x;
}

int main() {
    A a;  // OK: a.p指向a
    A b = f(); // 疑问:b.p是否可能因编译器是否应用RVO而悬垂,指向f内的x
    A c = A(); // (C++17之前) 疑问:若创建临时对象后销毁,c.p是否会悬垂
               // (C++17起) OK: c.p直接指向c,无临时对象参与
}

具体疑问

  1. 在A b = f();中,C++17之前的标准下,是否会因编译器是否应用返回值优化(RVO),导致b.p成为悬垂指针指向f函数内的x?
  2. 对于A c = A();,已知C17中c.p直接指向c且无临时对象,但C11/14中是否会因临时对象销毁导致c.p悬垂?

注:此代码无法在C03中编译,仅针对C11和C++14标准咨询。


解答

问题1:A b = f();的行为分析

在C++17之前,返回值优化(RVO)是编译器可选优化,标准不强制要求实现:

  • 若编译器启用RVO:f()中的x会直接在b的内存地址上构造,此时x.p(即最终的b.p)指向的就是b自身,不存在悬垂问题。
  • 若编译器不启用RVO:会先在f()栈帧内构造x(x.p指向x),再调用复制构造函数将x复制到b。如果复制构造函数采用默认实现(仅复制成员值),那么b.p会保留x的地址,而x在f()返回后会被销毁,此时b.p就会变成悬垂指针。不过你的代码仅声明了复制构造函数未定义,若走到这一步会触发链接错误。

实际开发中,主流编译器(GCC、Clang、MSVC)在优化模式下都会默认启用RVO,悬垂场景极少出现,但标准层面确实允许这种情况发生。

问题2:A c = A();的行为分析

在C++11/14中,该语句属于可选复制消除场景:

  • 若编译器启用优化:会直接在c的内存位置构造对象,跳过临时对象的创建,此时c.p指向c自身,无悬垂风险。
  • 若编译器不启用优化:会先构造临时对象(p指向临时对象),再将临时对象复制到c,随后销毁临时对象。如果复制构造函数未修改p的值,c.p会指向已销毁的临时对象,成为悬垂指针。

同样,主流编译器在优化模式下都会消除这个临时对象,但标准未强制要求,理论上存在悬垂可能。


内容的提问来源于stack exchange,提问作者sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:06:11