Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ pImpl的std::auto_ptr还是boost::shared_ptr?_C++_Boost_Stl_Shared Ptr_Auto Ptr - Fatal编程技术网

C++ pImpl的std::auto_ptr还是boost::shared_ptr?

C++ pImpl的std::auto_ptr还是boost::shared_ptr?,c++,boost,stl,shared-ptr,auto-ptr,C++,Boost,Stl,Shared Ptr,Auto Ptr,使用时,是否最好使用boost:shared_ptr而不是std::auto_ptr?我确信我曾经读到过boost版本更为异常友好 class Foo { public: Foo(); private: struct impl; std::auto_ptr<impl> impl_; }; class Foo { public: Foo(); private: struct impl; boost::shared_ptr<impl

使用时,是否最好使用
boost:shared_ptr
而不是
std::auto_ptr
?我确信我曾经读到过boost版本更为异常友好

class Foo
{
public:
    Foo();
private:
    struct impl;
    std::auto_ptr<impl> impl_;
};

class Foo
{
public:
    Foo();
private:
    struct impl;
    boost::shared_ptr<impl> impl_;
};
class-Foo
{
公众:
Foo();
私人:
结构impl;
标准::自动执行;
};
福班
{
公众:
Foo();
私人:
结构impl;
boost::共享\u ptr impl;
};

[P>[Ed]使用STD:AutoYPTR总是安全的吗?或者当需要一个替代的Boost智能指针时有发生吗?

< P>不要试图在脚上开枪,C++中你有很多机会: 实际上不需要使用任何一个自动指针,因为您完全知道对象何时应该进入和退出生命(在构造函数和析构函数中)


保持简单。

我倾向于使用
auto\u ptr
。确保类不可复制(声明private copy ctor&operator=,或者继承
boost::noncopyable
)。如果使用
auto_ptr
,一个缺点是需要定义非内联析构函数,即使正文是空的。(这是因为如果让编译器生成默认析构函数,
impl
将是一个不完整的类型,当调用
delete impl\uu
时,调用未定义的行为)


auto_ptr
和boost指针之间几乎没有选择余地。如果标准库替代方案可以,我倾向于从风格上不使用boost。

std::auto_ptr的boost替代方案是
boost::scoped_ptr
。与
auto_ptr
的主要区别在于
boost::scoped_ptr
是不可复制的


有关更多详细信息,请参阅。

如果您确实学究气十足,则无法绝对保证使用
自动\u ptr
成员时不需要在使用点完整定义
自动\u ptr
的模板参数。话虽如此,我从未见过这种方法行不通

一种变体是使用
常量auto_ptr
。只要您可以在初始化器列表中使用新的表达式构造“pimpl”,并保证编译器无法生成默认的复制构造函数和赋值方法,这一点就可以实现。仍然需要为封闭类提供非内联析构函数


在其他条件相同的情况下,我倾向于只使用标准库的实现,因为它可以使内容更具可移植性。

您不应该为此使用std::auto_ptr。析构函数在声明std::auto_ptr时不可见,因此可能无法正确调用它。这是假设您正向声明pImpl类,并在另一个文件中的构造函数内创建实例

如果您使用(此处不需要shared_ptr,您将不会与任何其他对象共享pimpl,这是由作用域_ptr实现的),那么您只需要在调用作用域_ptr构造函数的点处可见pimpl析构函数

例如

编译器将生成代码,在空析构函数中有效地“销毁”所有MyClass成员。因此,在auto_ptr析构函数被实例化时,Pimpl不再是不完整的,编译器现在知道如何调用析构函数


就我个人而言,我认为不值得为确保每件事都是正确的而烦恼。还有一种风险是,有人稍后会过来,通过删除看似冗余的析构函数来整理代码。因此,对于这类事情,使用boost::scoped_ptr更安全。

boost::shared_ptr是专门为pimpl习惯用法量身定制的。主要优点之一是它不允许为持有pimpl的类定义析构函数。共享所有权政策可能有利也有弊。但在以后的情况下,您可以正确地定义复制构造函数。

对于pImpl,共享ptr比自动ptr更可取,因为您的外部类在复制它时可能会突然丢失指针

通过shared_ptr,您可以使用前向声明的类型,这样就可以正常工作。auto_ptr不允许前向声明的类型。scoped_ptr也没有,如果您的外部类无论如何都是不可复制的,并且只有一个指针,那么它也可以是一个常规指针


在pImpl中使用侵入性引用计数,并让外部类在其实现中调用其副本和分配语义,有很多值得一提的地方。假设这是一个真正的供应商(提供类)模型,那么供应商最好不要强迫用户使用共享ptr,或者使用相同版本的共享ptr(boost或std)。

如果您想要一个可复制的类,请使用
作用域ptr
,它禁止复制,从而使您的类在默认情况下难以错误使用(与使用
shared\u ptr
相比,编译器本身不会发出复制功能;而在
shared\u ptr
的情况下,如果您不知道自己在做什么(即使对于向导来说,这通常也足够),当某个东西的副本突然也修改了该东西时,会出现奇怪的行为),然后定义复制构造函数和复制赋值:

class CopyableFoo {
public:
    ...
    CopyableFoo (const CopyableFoo&);
    CopyableFoo& operator= (const CopyableFoo&);
private:
    scoped_ptr<Impl> impl_;
};

...
CopyableFoo (const CopyableFoo& rhs)
    : impl_(new Impl (*rhs.impl_))
{}
类CopyableFoo{
公众:
...
CopyableFoo(constcopyablefoo&);
CopyableFoo&运算符=(const CopyableFoo&);
私人:
范围内的ptr impl;
};
...
CopyableFoo(const CopyableFoo&rhs)
:impl_(新impl(*rhs.impl_))
{}

我真的很高兴。它使创建pImpl变得非常容易,而不需要显式复制构造函数和赋值运算符


我已经修改了原始代码,因此它现在类似于一个共享的ptr,因此它可以在epilog代码中使用,并且保持快速。

强烈反对。这种方法不会防止在创建impl对象后在ctor本身引起的异常。当这种情况发生时,不会调用dtor,并且会泄漏impl对象。如果你使用pimpl习语,它不是un
// in MyClass.h

class Pimpl;

class MyClass 
{ 
private:
    std::auto_ptr<Pimpl> pimpl;

public: 
    MyClass();
    ~MyClass();
};
// in MyClass.cpp

#include "Pimpl.h"

MyClass::MyClass() : pimpl(new Pimpl(blah))
{
}

MyClass::~MyClass() 
{
    // this needs to be here, even when empty
}
class CopyableFoo {
public:
    ...
    CopyableFoo (const CopyableFoo&);
    CopyableFoo& operator= (const CopyableFoo&);
private:
    scoped_ptr<Impl> impl_;
};

...
CopyableFoo (const CopyableFoo& rhs)
    : impl_(new Impl (*rhs.impl_))
{}