例如
<div>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA</div>
通常哪个选项更好?
我在Visual Studio 2017上做了基准测试。在我测试的所有情况下,选项2都给了我最好的性能。在某些情况下,选项3具有与选项2类似的性能,但有些情况更糟。谢谢!
答案 0 :(得分:0)
在您的情况下,选项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值引用,引用ptr
,因此ptr变为空。然后将它从参数列表移动到成员,参数为null。你看,没有(需要一个)副本,这意味着更改了引用计数器。
我更喜欢T const&
仅用于仅从引用读取且不用于初始化另一个变量的函数。如果在示例中使用了带引用的第三个选项,则需要复制指针,因为setI_3的主体在赋值语句中有一个副本(不移动)。
第一个选项显然是最差的,因为指针被多次复制。
当您将shared_ptr
与unique_ptr
交换时,编译器强制您尽可能使用最快的方法 - 移动。
我会添加第四个选项:
// Option 4
void setI_4(shared_ptr<int>&& i) { m_i = move(i); }
请注意,即使i
是一个r值引用,它在代码中使用时也不是r值引用,因此在没有移动时会被复制;
第四个选项只与第二个选项不同,传递的参数总是需要是一个r值引用,而在第二个选项中,i
本身就是一个指针变量,在第四个选项中i
是一个引用(函数体可以执行任何操作,但它存在于函数之外(std :: move允许执行此操作))。参数变量是从调用者的参数元组中的表达式构造的,shared_ptr
的构造函数自动复制指针(这意味着参考计数器增加),如果它不是r值 - 参考
调用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
};
};
};