C++中指向栈变量的std::shared_ptr行为不符预期,求解析
第一个实验的问题
你完全搞错了std::make_shared<Rectangle>(r)的本质——它不是让shared_ptr指向栈上的r,而是会在堆内存中创建一个全新的Rectangle对象,然后用栈上的r作为参数(调用拷贝构造函数)初始化这个堆对象。
返回的shared_ptr管理的是这个堆上的拷贝,和栈上的r没有任何关联。栈上的r确实会在函数结束时销毁,但这对堆上的拷贝毫无影响,所以代码正常输出6是完全合理的,根本不存在悬空指针的问题。
裸指针实验的合理性
这个实验才是真正的“返回栈变量指针”:你直接返回了&r,也就是栈上对象的内存地址。函数结束后r被销毁,该地址对应的内存变成无效区域,访问它属于未定义行为——输出垃圾值是这种行为的典型表现(当然未定义行为也可能碰巧输出正确值,只是你这次没遇到)。
第三个实验的逻辑错误
rectPtr管理的依然是堆上的拷贝,它在if块结束时销毁的是堆上的那个对象,和栈上的r无关。后面返回的make_shared<Rectangle>(r)又会重新拷贝r到新的堆对象,所以返回的shared_ptr依然有效,自然能正常输出。
关于编译器优化的疑问
不存在“编译器优化导致变量未销毁”的情况——栈变量在作用域结束时一定会被销毁(其内存会被标记为可复用),但你的shared_ptr从始至终都没指向过栈变量,所以根本不存在悬空的场景。只有裸指针的情况才是真正的未定义行为,这类行为的表现完全不可预测,取决于编译器、运行环境等因素。
内容的提问来源于stack exchange,提问作者sousben
相关产品推荐
相关产品推荐

