如何:创建和使用shared_ptr实例

2025-05-17 13:42:44
推荐回答(2个)
回答1:

make_shared 是异常安全的。它使用同一调用分配的内存控制块和该资源从而减少构造开销。如果不使用 make_shared,则必须使用显式新的表达式创建对象,然后将其传递给 shared_ptr 构造函数之前。下面的示例演示各种方式与新的对象同时声明和初始化 shared_ptr。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 下面的示例演示如何声明和初始化采用对象共享所有权另一 shared_ptr已分配的 shared_ptr 实例。假定,sp2 是初始化的 shared_ptr。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. shared_ptr 也很有用在标准模板库 (STL) 容器,当您使用"复制元素的算法时。可以包装在 shared_ptr的元素,然后将其复制到完全理解的其他容器基础内存有效,只要不需要且不再。下面的示例在矢量演示如何使用在 shared_ptr 实例的 replace_copy_if 算法。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 可以使用 dynamic_pointer_cast、static_pointer_cast和const_pointer_cast 转换shared_ptr。这些功能类似于 dynamic_cast、static_cast和const_cast 运算符。下面的示例演示如何测试每个元素的派生类型在基类 shared_ptr 矢量的,然后复制元素并显示有关它们的信息。VBC#C++F#JScriptPowerShell No code example is currently available or this language may not be supported. 可以通过以下方式通过 shared_ptr 到另一个函数:通过shared_ptr 值。此调用复制构造函数,会递增引用计数,并使被调用方所有者。具有此操作的少量系统开销,可能是有意义的根据经历 shared_ptr 对象通过。使用此选项,当代码协定 (提示或显式) 时在调用方和被调用方之间要求被调用方是所有者。通过shared_ptr 引用或常数引用。在这种情况下,引用计数不增加,因此,被调用方可以访问指针,只要调用方不超出范围。或者,则被调用方可以决定创建基于引用的 shared_ptr 从而形成一个共享的所有者。使用此选项,当调用方不了解被调用方时,或者,如果必须通过 shared_ptr 和若要出于性能原因时避免复制操作。通过基础指针或引用为基础对象。这使得被调用方使用对象,但是,不使共享所有权或扩展生存期。如果被调用方创建原始指针的 shared_ptr,新 shared_ptr 与原来的是独立的和不控制此类基础资源。使用此选项,则在调用方和被调用方之间的协定的清单指定时调用方保留 shared_ptr 生存期的所有权。当您决定如何通过 shared_ptr,确定被调用方是否必须共享这种基础资源的所有权。“所有者”是可以使这种基础资源运行的对象或函数,只要它需要它。如果调用方必须确保则被调用方可以扩展指针的生存期在其 (函数) 的生存期以外的,请使用第一个选项。如果您不关心被调用方是否扩展生存期,则可以通过引用并允许被调用方复制它。如果必须允许帮助器到基础指针的函数访问,因此,您了解 helper 函数将使用指针和返回,在被调用函数返回以前,则该函数不必共享基础指针的所有权。它必须对调用方的 shared_ptr的生存期内指针。在这种情况下,通过 shared_ptr 引用或通过原始的指针或引用为基础对象是安全的。通过此方式提供一个小的性能改进,并且还有助于表示您编程的用途。

回答2:

  使用 weak_ptr 以确保正确删除循环依赖关系对象的实例。 检查示例时,假定它是仅在考虑备用解决方案后才创建的。

  Controller 对象表示设备处理的某个方面,并且能独立运行。 每个控制器必须能够在任何时间查询其他控制器的状态,因此,每个控制器包含私有 vector>。 由于每个向量包含一个循环引用,因此使用 weak_ptr 实例而不是 shared_ptr。

参考例子如下:

#include 
#include 
#include 
#include 
#include 

using namespace std;

class Controller 
{
public:
    int Num;
    wstring Status;
    vector> others;
    explicit Controller(int i) : Num(i) , Status(L"On")
    {
        wcout << L"Creating Controller" << Num << endl;
    }

    ~Controller()
    {
        wcout << L"Destroying Controller" << Num << endl;
    }

    // Demonstrates how to test whether the   
    // pointed-to memory still exists or not.  
    void CheckStatuses() const
    {
        for_each(others.begin(), others.end(), [] (weak_ptr wp)
        {
            try
            {
                auto p = wp.lock();
                wcout << L"Status of " << p->Num << " = " << p->Status << endl;
            }

            catch (bad_weak_ptr b)
            {
                wcout << L"Null object" << endl;
            }                
        });
    }
};

void RunTest()
{
    vector> v;

    v.push_back(shared_ptr(new Controller(0)));
    v.push_back(shared_ptr(new Controller(1)));
    v.push_back(shared_ptr(new Controller(2)));
    v.push_back(shared_ptr(new Controller(3)));
    v.push_back(shared_ptr(new Controller(4)));

    // Each controller depends on all others not being deleted.  
    // Give each controller a pointer to all the others.  
    for (int i = 0 ; i < v.size(); ++i)
    {
        for_each(v.begin(), v.end(), [v,i] (shared_ptr p)
        {
            if(p->Num != i)
            {
                v[i]->others.push_back(weak_ptr(p));
                wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
            }
        });        
    }

    for_each(v.begin(), v.end(), [](shared_ptr& p)
    {
        wcout << L"use_count = " << p.use_count() << endl;
        p->CheckStatuses();
    });
}

int main()
{    
    RunTest(); 
    wcout << L"Press any key" << endl;
    char ch;
    cin.getline(&ch, 1);
}