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

链式重载成员访问operator->时临时对象的生存期问题

C++中operator->重载的合法性与临时对象生存期解析

先看你提供的代码示例:

struct A {
  int data;
  A* operator->() { return this; }
};

struct B {
  A operator->() { return A(); }
};

struct C {
  B operator->() { return B(); }
};

int main() {
  C()->data = 1;
}

1. 重载operator->()返回this指针是否合法?有哪些潜在问题?

完全合法。C++标准对operator->()的返回值要求只有两个:要么是指针类型,要么是重载了operator->()的类/结构体类型。A*属于指针类型,完全符合语法规则,编译器不会抛出错误。

但这种写法确实存在明显的悬垂指针风险:如果调用operator->()的A对象是临时对象(比如示例中B::operator->()返回的A()),那么当这个临时对象的生存期结束后,返回的this指针就会变成无效的悬垂指针。后续如果通过这个指针访问成员,会触发未定义行为——不过在你的示例表达式里,赋值操作是在临时对象存活期间完成的,所以不会触发这个问题。

2. 链式重载operator->()中的临时对象生存期有何标准保证?

C++标准有明确规定:临时对象的生存期会延续到包含它的完整表达式结束时,不会在求值过程中中途销毁。

回到你的核心疑问:表达式C()->data = 1的求值过程不会被拆分成“先存储指针再访问成员”的两步,而是等价于连续的链式调用:

(((C().operator->()).operator->()).operator->())->data = 1;

整个赋值语句是一个完整表达式,其中所有临时对象(C()临时实例、B::operator->()返回的B临时实例、A::operator->()返回的A临时实例)都会在整个赋值操作完成后才被销毁。因此,访问data并赋值的操作是在A临时对象存活期间进行的,完全合法。

需要注意的是:如果你把operator->()返回的指针存储到一个持久变量中,后续再通过该指针访问成员,此时临时对象已经销毁,就会触发悬垂指针的未定义行为——但这属于使用方式的问题,和operator->()的链式调用规则无关。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 07:16:11