首页 > 解决方案 > 是否可以返回对静态或动态指针转换结果的引用?

问题描述

所以假设我有以下功能:

    template<typename T>
    std::shared_ptr<T> resourceAs() const {
        return std::static_pointer_cast<T>(m_resource);
    }

这行得通。但是如果我不喜欢创建 shared_ptr 的小开销怎么办?如果我想要这样的东西怎么办

    template<typename T>
    const std::shared_ptr<T>& resourceAs() const {
        return std::static_pointer_cast<T>(m_resource);
    }

所以,这里的问题是编译器会对我返回一个局部变量不满意。有没有一种安全的方法可以返回对我的成员类型的强制转换指针的引用?我的直觉告诉我没有,但我很好奇。

标签: c++pointerscastingreference

解决方案


std::static_pointer_cast<T>(m_resource);

此函数调用返回一个对象,而不是对对象的引用。

std::static_pointer_cast将现有对象std::shared_ptr作为参数,并创建一个新std::shared_ptr对象(用于不相关的特定目的)。它不返回对现有对象的引用std::shared_ptr,而是返回一个新std::shared_ptr对象。

因此,如果返回的std::static_pointer_cast<T>内容存储在某个变量中,那么就会发生这种情况。如果没有,它就会被摧毁。

在 C++ 中,获得对对象的引用并不能防止底层对象在正常情况下被销毁(此规则有一个古怪的例外,即临时对象生命周期扩展规则,但它不适用于此处)。

您尝试的替代方法resourceAs()获得了对返回的引用std::shared_ptr,并将其返回。但是,由于 this std::shared_ptr(从 中返回std::static_pointer_cast)实际上并没有被存储在任何地方,然后被销毁,就像任何其他声明为本地的对象resourceAs()会在从该函数返回时被销毁一样。

这不是特定于 的std::shared_ptr,这就是所有对象在 C++ 中的工作方式,同样的事情也会发生在 C++ 中任何其他包含相同课程的对象上:

class apple {

     // ...

};

apple buy_a_fruit();

const apple &what_i_bought()
{
     return buy_a_fruit();
}

what_i_bought()返回对从 中返回的对象的引用buy_a_fruit(),但对象本身被销毁,留下对已销毁对象的引用。

结果引用没有有效的用法。现代 C++ 编译器足够聪明,可以检测到这个错误并发出诊断警报。


推荐阅读