19人参与 • 2026-08-02 • C/C++
static amf0value make_number(double v) {
amf0value a;
a.type = amf0_number;
a.number = v;
return a;
}
看这个"东西"在函数返回之后,是否还"活着"。活着 → 安全;已经被销毁了却还在引用它 → 悬空(dangling),未定义行为。
amf0value make_number(double v) {
amf0value a; // 局部变量
return a; // 返回的是"值",销毁a之前会先把内容搬给调用者
}
调用者拿到的是独立的新数据,跟原来的 a 无关。a 死不死不重要。这是 amf0.h 里 make_number/make_bool/make_string 这些工厂方法的写法,天然安全。
为什么安全:函数返回类型是 amf0value(值),不是 amf0value&(引用)也不是 amf0value*(指针)。return a; 这一步,是在 a 被销毁之前,先把 a 的内容拷贝 (或者移动)一份给调用者。等这个"搬运"动作完成之后,函数才真正结束,局部变量 a 才被销毁——调用者手里的东西跟 a 已经没关系了。
类比 java:java 里 amf0value a = new amf0value();,a 本质是一个指向堆上对象 的引用,方法返回 a 返回的也是这个引用(地址),指向的还是堆上同一个对象,对象生死 由 gc 管,跟方法作用域无关。c++ 不一样:amf0value a; 默认是栈上的真实对象,作用域 结束是真的会销毁的。正因为这样,c++ "返回值"这个动作,语义上就是"把值搬到外面", 而不是"返回一个指向它的地址"。
amf0value& make_number_bad(double v) {
amf0value a;
return a; // 函数结束 a 被销毁,这个引用悬空
}
amf0value* make_number_bad2(double v) {
amf0value a;
return &a; // 同样悬空
}
记住"局部变量 + 引用/指针返回"这个组合就行——这是最经典也是最容易踩的坑。
// 安全:外面传进来的对象,函数结束后它在调用者那边继续活着
const std::string& first_nonempty(const std::string& a, const std::string& b) {
return a.empty() ? b : a; // a、b 都是调用者的对象,没被这个函数销毁
}
// 危险:value 是"传值"进来的参数,本质也是这个函数的局部变量
const std::string& make_bad(std::string value) {
return value; // value 是这个函数自己的局部拷贝,函数结束就销毁了
}
struct amf0value {
std::vector<std::pair<std::string, std::shared_ptr<amf0value>>> obj;
const amf0value* get(const std::string& key) const {
for (auto& kv : obj) if (kv.first == key) return kv.second.get();
return nullptr;
}
};
这个 get() 项目里就有——只要拿到这个指针的时候,那个 amf0value 对象本身还没被 销毁,就是安全的。但如果把这个对象整个销毁了,之前 get() 拿到的指针立刻变悬空, 这不是函数的问题,是调用方要自己保证"对象还活着才能用它返回的指针"。
这个跟"局部变量"无关,但是同一类"东西已经不在了却还在用"的问题,值得一起记住:
const amf0value* p = obj_value.get("app"); // 假设此刻拿到了一个指针
obj_value.set("newkey", ...); // vector push_back,可能触发扩容重新分配内存
// p 现在可能已经悬空了!因为 vector 扩容时会把所有元素搬到新内存,
// 旧内存被释放,p 指向的地址不再有效
这叫迭代器/引用失效(iterator/reference invalidation),跟局部变量销毁是两码事, 但本质都是"你手里的指针/引用指向的内存已经不归你想的那个对象用了"。规则:只要还 可能对容器做增删操作,就不要长期持有指向它内部元素的指针/引用。
amf0value* p = new amf0value(); // 堆上分配,函数结束不会自动销毁 return p; // 这个指针指向的对象还活着,不悬空
| 返回什么 | 安不安全 | 原因 |
|---|---|---|
| 局部变量的值 | ✅ 安全 | 销毁前先拷贝/移动出去 |
| 局部变量的引用/指针 | ❌ 危险 | 函数结束就销毁,引用/指针悬空 |
| 传引用进来的参数的引用 | ✅ 安全 | 对象在调用者那边,函数没有权力销毁它 |
| 传值进来的参数的引用 | ❌ 危险 | 参数本身也是局部变量 |
| 类成员的引用/指针 | ⚠️ 看情况 | 只要 *this 对象还活着就安全 |
| 容器内部元素的指针(之后又改了容器) | ❌ 危险 | 容器扩容/删除会让内部指针失效 |
| new/shared_ptr 管理的对象 | ✅ 不悬空 | 但要小心生命周期归属(泄漏/重复释放) |
记忆口诀:先问自己"这块内存归谁管、什么时候会被回收",再看你手里的引用/指针会 不会活得比它管理的内存还长。
到此这篇关于c++ 返回值失效的问题解决的文章就介绍到这了,更多相关c++ 返回值失效内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论