以下是创建Stuff并赋予Foo所有权的合理有效方法吗?
class Foo
{
explicit Foo(const std::shared_ptr<Stuff>& myStuff)
: m_myStuff(myStuff)
{
}
...
private:
const std::shared_ptr<Stuff> m_myStuff;
}
std::shared_ptr<Stuff> foosStuff(new Stuff());
Foo f(foosStuff);
答案 0 :(得分:22)
既然你对效率感兴趣,我想提出两点:
的shared_ptr&LT;&GT;是移动构造比复制构造便宜的许多标准库类型之一。复制构造shared_ptr较慢,因为复制需要引用计数器以原子方式递增,而移动shared_ptr则根本不需要触摸引用的数据或计数器。从Dave Abrahams的文章“Want Speed? Pass by value!”可以了解到,在某些情况下,按值获取函数参数实际上是有益的。这是其中一种情况:
class Foo
{
explicit Foo(std::shared_ptr<Stuff> myStuff)
: m_myStuff(move(myStuff))
{}
...
private:
std::shared_ptr<Stuff> m_myStuff;
};
现在你可以写
了Foo f (std::make_shared<Stuff>());
其中参数是临时的,并且没有复制shared_ptr(只移动一次或两次)。
这里使用std :: make_shared的优点是只进行了一次分配。在您的情况下,您自己分配了Stuff对象,而shared_ptr构造函数也必须动态分配引用计数器和删除器。只需一次分配,make_shared就能为您完成所有工作。
答案 1 :(得分:4)
是的,这是完全合理的。这样,管理共享指针所涉及的工作只需要完成一次,而不是两次,如果你按值传递它。您还可以考虑使用make_shared来避免复制构造。
std::shared_ptr<Stuff> foosStuff(std::make_shared<Stuff>());
你可以做的唯一改进是如果Foo是唯一的所有者(即你在创建Foo之后不会保留foosStuff)然后你可以切换到使用std :: unique_ptr或boost :: scoped_ptr (这是前C ++ 11的等价物),它的开销会更少。
答案 2 :(得分:3)
拥有make_foo
帮助器可能更有效:
Foo make_foo() { return Foo(std::make_shared<Stuff>()); }
现在你可以说auto f = make_foo();
。或者至少自己使用make_shared
调用,因为生成的shared_ptr
可能比从new
表达式构造的Stuff
更有效。如果struct Foo
{
template <typename ...Args>
static Foo make(Args &&... args)
{
return Foo(direct_construct(), std::forward<Args>(args)...);
};
private:
struct direct_construct{};
template <typeaname ...Args>
Foo(direct_construct, Args &&... args)
: m_myStuff(std::make_shared<Stuff>(std::forward<Args>(args)...)) // #1
{ }
};
实际上采用构造函数参数,则私有辅助构造函数可能是合适的:
Foo::make
您可以将make_foo
打包到上面的auto f = Foo::make(true, 'x', Blue);
中,也可以直接使用它:
std::unique_ptr<Stuff>
那就是说,除非你真的分享所有权,否则m_myStuff(new Stuff(std::forward<Args>(args)...))
听起来更为可取:它在概念上更简单,也更有效。在这种情况下,您会在标有#1
的行中说{{1}}。