如何通过更好的性能传递和共享共享的所有权

How to pass and share shared_ptr ownership with a better performance?

本文关键字:共享 所有权 性能 何通过 更好      更新时间:2023-10-16

例如

class A
{
public:
    // Option 1
    void setI_1(shared_ptr<int> i) { m_i = i; }
    // Option 2
    void setI_2(shared_ptr<int> i) { m_i = move(i); }
    // Option 3
    void setI_3(shared_ptr<int> const& i) { m_i = i; }
private:
    shared_ptr<int> m_i;        
};

通常哪种选项更好?

我在Visual Studio 2017上进行基准测试。选项2在所有测试的情况下,我都提供了最佳性能。在某些情况下,选项3的性能与选项2相似,但有些情况更糟。谢谢!

在您的情况下,选项2是最好的情况。您可能需要将指针移至课程,因此,当您不再需要它时,您无需一次又一次地增加参考表:

{
    shared_ptr<int> ptr = std::make_shared<int>(42);
    A a;
    a.setI_2(std::move(ptr)); // I no longer need ptr, so I can move it
};

指针移动到参数列表,ptr为null/参数以R-Value-Reference初始化为ptr,以便PTR获取null。然后将其从参数列表移动到成员,参数为null。您看到,没有(需要a(副本,这意味着参考counter的更改。

我只喜欢T const&对于仅从参考读取并且不用于初始化另一个变量的函数。如果在示例中使用了带有引用的第三个选项,则需要复制指针,因为seti_3的主体在分配语句中具有副本(无移动(。

第一个选择显然是最坏的,因为指针被多次复制。

当您将shared_ptrunique_ptr交换时,编译器迫使您使用最快的方式 - 移动。

我会添加第四个选项:

// Option 4
void setI_4(shared_ptr<int>&& i) { m_i = move(i); }

请注意,即使是 i bee bee bee r-value-reference,在代码中使用时,它也不是r-value-reference,因此在没有移动时也会复制;

第四个选项仅与第二个选项不同,即传递的参数始终需要是r-value-Reference,而在第二个选项中,第二个选项是单独使用的i是一个指针变量,而在第四个i中是参考。(对于功能的主体可以做任何事情,但它生活在功能之外(std :: Move允许这样做((。参数变量是由来自呼叫者的参数核中的表达式构造的,如果不是R-Value-Reference,则shared_ptr的构造函数自动复制指针(这意味着增加参考点(。p> seti_2的调用如下:

{
    shared_ptr<int> ptr = std::make_shared<int>(42);
    /// ptr owns 42
    A a;
    {   // a.setI_2(std::move(ptr));
        // initializing the parameter
        shared_ptr<int> i{std::move(ptr)};
        // now i owns 42 and ptr no longer owns it and points to null
        {   // the body of the function
            a.m_i = std::move(i);
            // now a.m_i owns 42 and i no longer owns it and points to null
        };
    };
};