在C++中使用共享指针更容易的方法 我正忙着设计一个新的C++应用程序。在这个应用程序中,我希望用指针最小化潜在错误,并且由于应用程序应该是纯C++ NO.NET或其他新奇事物,所以我正在研究共享指针,我考虑到处使用共享指针而不是普通指针。
我想出了一些技巧来简化共享指针的使用,例如:在类中使用typedef,如下所示:在C++中使用共享指针更容易的方法 我正忙着设计一个新的C++应用程序。在这个应用程序中,我希望用指针最小化潜在错误,并且由于应用程序应该是纯C++ NO.NET或其他新奇事物,所以我正在研究共享指针,我考虑到处使用共享指针而不是普通指针。,c++,visual-studio-2010,c++11,shared-ptr,C++,Visual Studio 2010,C++11,Shared Ptr,我想出了一些技巧来简化共享指针的使用,例如:在类中使用typedef,如下所示: class X { public: ... typedef std::shared_ptr<X> Ptr; }; namespace boost { template< typename T > class shared_ptr; } namespace MyStuff { class Foo; class Bar; class
class X
{
public:
...
typedef std::shared_ptr<X> Ptr;
};
namespace boost { template< typename T > class shared_ptr; }
namespace MyStuff
{
class Foo;
class Bar;
class Baz;
typedef boost::shared_ptr<Foo> FooPtr;
typedef boost::shared_ptr<Bar> BarPtr;
typedef boost::shared_ptr<Baz> BazPtr;
}
通过这种方式,您可以轻松地编写X::Ptr,这比在任何地方编写std::shared_Ptr都要容易
我还注意到共享指针的一些缺点:
struct X;
...
std::shared_ptr<X> ptr; // legal
struct X {};
ptr = std::shared_ptr<X>(new X); // legal
无论我在哪里使用我需要包含的共享指针
如果我只想使用指针,我就不能再使用前向声明了
有没有其他方法可以让共享指针更容易使用?关于typedef,您应该看看哪些方法可以解决完全相同的问题
对于第二部分,我认为您错了,因为std::shared_ptr可用于N3225的20.9.10.2/2中规定的不完整类型:
shared_ptr的模板参数T
可能是不完整的类型
如果您当前的实现不支持这一点,我认为这应该被视为一个bug。关于typedef,您应该看看哪些解决了完全相同的问题
对于第二部分,我认为您错了,因为std::shared_ptr可用于N3225的20.9.10.2/2中规定的不完整类型:
shared_ptr的模板参数T
可能是不完整的类型
如果您当前的实现不支持这一点,我认为这应该被视为一个bug。不要只选择一个智能指针在任何地方使用。不是每个螺丝都是十字头 此外,您可以对任何智能指针使用与原始指针完全相同的正向声明:
struct X;
...
std::shared_ptr<X> ptr; // legal
struct X {};
ptr = std::shared_ptr<X>(new X); // legal
这是我第二次在SO上听到这种误解,它完全是错误的。不要只选择一个智能指针,在任何地方都可以使用。不是每个螺丝都是十字头 此外,您可以对任何智能指针使用与原始指针完全相同的正向声明:
struct X;
...
std::shared_ptr<X> ptr; // legal
struct X {};
ptr = std::shared_ptr<X>(new X); // legal
这是我第二次听到这样的误解,它完全是错误的。不要
最小化指针错误的唯一方法是使用正确的指针类型。这就是类型,复数
共享指针不是万能的。当你有周期性引用时,它们就会变成内存泄漏,如果你打算在任何地方都使用它们,那么它们很快就会出现
如果你想要无错误的C++应用程序,你必须为它工作。你必须了解你的申请。您必须理解不同对象的所有权语义。共享指针只提供共享所有权,这通常是一个合理的最低分母。其他的一切都可以被共享所有权所取代,它会起作用的
但默认情况下,一个对象由另一个实体拥有。它由一个函数拥有,并且应该在该函数返回时销毁,或者它由一个类或其他任何东西拥有。通常,您根本不需要指针。对象可能是通过std::vector中的值存储的。或者它只是一个局部变量或类成员。如果它是一个指针,通常最好用一个作用域\u ptr或一个允许所有权转移的唯一\u ptr或自动\u ptr来表示 当您无法保证对象的生存期或所有权时,您可能会求助于shared_ptr。但当你使用它时,你也需要使用弱ptr来打破循环 实际上,更好的方法是尽可能避免指针。当您确实需要一个指针时,请使用一个具有最具体的所有权语义的指针。首选作用域\u ptr,它根本不允许所有权转移,如果您需要它,请使用一个允许您移动所有权的指针,例如unique \u ptr,并且仅作为最后手段,您才应使用shared \u ptr,它允许您在任意数量的客户端之间自由共享所有权 没有任何魔杖可以让你的C++代码工作。实现这一点的唯一方法就是编写好的C++代码。你通过了解并使用你可以使用的工具来做到这一点,而不是假装嘿,shared_ptr就像一个垃圾收集器,不是吗?如果我使用它,我可以忽略所有关于对象生存期或内存泄漏的问题。不要 最小化指针错误的唯一方法是使用正确的指针类型。这就是类型,复数 共享指针不是万能的。当你有周期性引用时,它们就会变成内存泄漏,如果你打算在任何地方都使用它们,那么它们很快就会出现如果你想要无错误的C++应用程序,你必须为它工作。你必须了解你的申请。您必须理解不同对象的所有权语义。共享指针只提供共享的o 所有权,这通常是一个体面的最低分母。其他的一切都可以被共享所有权所取代,它会起作用的
但默认情况下,一个对象由另一个实体拥有。它由一个函数拥有,并且应该在该函数返回时销毁,或者它由一个类或其他任何东西拥有。通常,您根本不需要指针。对象可能是通过std::vector中的值存储的。或者它只是一个局部变量或类成员。如果它是一个指针,通常最好用一个作用域\u ptr或一个允许所有权转移的唯一\u ptr或自动\u ptr来表示 当您无法保证对象的生存期或所有权时,您可能会求助于shared_ptr。但当你使用它时,你也需要使用弱ptr来打破循环 实际上,更好的方法是尽可能避免指针。当您确实需要一个指针时,请使用一个具有最具体的所有权语义的指针。首选作用域\u ptr,它根本不允许所有权转移,如果您需要它,请使用一个允许您移动所有权的指针,例如unique \u ptr,并且仅作为最后手段,您才应使用shared \u ptr,它允许您在任意数量的客户端之间自由共享所有权没有任何魔杖可以让你的C++代码工作。实现这一点的唯一方法就是编写好的C++代码。你通过了解并使用你可以使用的工具来做到这一点,而不是假装嘿,shared_ptr就像一个垃圾收集器,不是吗?如果我使用它,我可以忽略所有关于对象生存期或内存泄漏的问题。在代码中,有一个约定是很常见的,然后您就可以遵循,只要在您的团队中一致地这样做,人们就能够理解它 在转发文件中声明共享指针typedef要好得多。大概是这样的:
class X
{
public:
...
typedef std::shared_ptr<X> Ptr;
};
namespace boost { template< typename T > class shared_ptr; }
namespace MyStuff
{
class Foo;
class Bar;
class Baz;
typedef boost::shared_ptr<Foo> FooPtr;
typedef boost::shared_ptr<Bar> BarPtr;
typedef boost::shared_ptr<Baz> BazPtr;
}
有时,您可能希望使用除shared_ptr之外的其他指针,但您的约定是使用不同的表示法,其中XPtr表示shared_ptr
当然,您可能会使用不同的表示法
我想我们用FooWeakPtr来表示弱
FooConstPtr是指共享的\u ptr
比如说
应该在您的编码标准文档中。在代码中,有一个约定是很常见的,然后您就可以遵循这个约定,只要您的团队等一致地这样做,人们就能够理解它 在转发文件中声明共享指针typedef要好得多。大概是这样的:
class X
{
public:
...
typedef std::shared_ptr<X> Ptr;
};
namespace boost { template< typename T > class shared_ptr; }
namespace MyStuff
{
class Foo;
class Bar;
class Baz;
typedef boost::shared_ptr<Foo> FooPtr;
typedef boost::shared_ptr<Bar> BarPtr;
typedef boost::shared_ptr<Baz> BazPtr;
}
有时,您可能希望使用除shared_ptr之外的其他指针,但您的约定是使用不同的表示法,其中XPtr表示shared_ptr
当然,您可能会使用不同的表示法
我想我们用FooWeakPtr来表示弱
FooConstPtr是指共享的\u ptr
比如说
应该在您的编码标准文档中。我更喜欢这种方法:
namespace Internal
{
template <class T>
struct DeclareShared
{
typedef std::shared_ptr<T> type;
};
template <class T>
struct DeclareUnique
{
typedef std::unique_ptr<T> type;
};
}
// Inherit one of these classes to use a generic smart pointer interface.
// If class is abstract, use this interface.
template <class T>
struct SharedAbstract
{
typedef typename Internal::DeclareShared<T>::type APtr;
};
template <class T>
struct Shared
{
typedef typename Internal::DeclareShared<T>::type Ptr;
template <class... P>
static Ptr shared(P&&... args)
{
return std::make_shared<T>(std::forward<P>(args)...);
}
};
template <class T>
struct UniqueAbstract
{
typedef typename Internal::DeclareUnique<T>::type AUPtr;
};
template <class T>
struct Unique
{
typedef typename Internal::DeclareUnique<T>::type UPtr;
template <class... P>
static UPtr shared(P&&... args)
{
return std::unique_ptr<T>(new T(std::forward<P>(args)...));
}
};
为作用域ptr等添加了更多接口,您可以执行以下操作:
struct Foo : public Shared<Foo>, public Unique<Foo>
{};
Foo::Ptr foo = Foo::shared();
Foo::UPtr unique = Foo::unique();
我不确定VS10如何处理可变模板,但这至少在GCC4.5+上运行良好。我更喜欢这种方法:
namespace Internal
{
template <class T>
struct DeclareShared
{
typedef std::shared_ptr<T> type;
};
template <class T>
struct DeclareUnique
{
typedef std::unique_ptr<T> type;
};
}
// Inherit one of these classes to use a generic smart pointer interface.
// If class is abstract, use this interface.
template <class T>
struct SharedAbstract
{
typedef typename Internal::DeclareShared<T>::type APtr;
};
template <class T>
struct Shared
{
typedef typename Internal::DeclareShared<T>::type Ptr;
template <class... P>
static Ptr shared(P&&... args)
{
return std::make_shared<T>(std::forward<P>(args)...);
}
};
template <class T>
struct UniqueAbstract
{
typedef typename Internal::DeclareUnique<T>::type AUPtr;
};
template <class T>
struct Unique
{
typedef typename Internal::DeclareUnique<T>::type UPtr;
template <class... P>
static UPtr shared(P&&... args)
{
return std::unique_ptr<T>(new T(std::forward<P>(args)...));
}
};
为作用域ptr等添加了更多接口,您可以执行以下操作:
struct Foo : public Shared<Foo>, public Unique<Foo>
{};
Foo::Ptr foo = Foo::shared();
Foo::UPtr unique = Foo::unique();
我不确定VS10如何处理可变模板,但这至少在GCC4.5+上运行良好。我在声明上可能不完整,但在使用上可能不完整。与T*@BatchyX不同,shared_ptr依赖于T的析构函数,因此在使用析构函数时,就像使用delete时一样,定义必须可用。没有这么大的变化。并非每次使用shared_ptr都会导致析构函数调用。例如,只返回从容器检索到的指针的函数不必销毁任何内容,并且可以使用不完整的类型来完成。用共享的\u ptr替换此指针会强制定义类型,即使无法在此函数中调用delete。我可以在声明上不完整,但在使用上不完整。与T*@BatchyX不同,shared_ptr依赖于T的析构函数,因此在使用析构函数时,就像使用delete时一样,定义必须可用。没有这么大的变化。并非每次使用shared_ptr都会导致析构函数调用。例如,只返回从容器检索到的指针的函数不必销毁任何内容,并且可以使用不完整的类型来完成。用共享\u ptr替换此指针会强制定义类型,即使无法在此函数中调用delete。我使用了您之前建议的typedef,但停止了这样做,因为我发现直接使用共享\u ptr更具可读性。相反,我更喜欢将shared_ptr拉入全局名称空间,以便通过使用std::shared_ptr;更容易编写;。我使用了你之前建议的typedef,但我不再这么做了,因为我发现直接使用shared_ptr更具可读性。在里面
相反,我更喜欢将shared_ptr拉入全局名称空间,以便通过使用std::shared_ptr;更容易编写;。个人品味的问题tho.叫喊“不要”有点过于戏剧化:-小心你不太想做的事情可能对人们的虚拟耳朵稍微好一点。否则我完全同意。事实上,由于它的工作原理,shared_ptr可以在向本地对象传递指针的情况下发挥作用。您可以将deleter设置为null操作,然后将其发送到下一行。你当然打破了关于共享的每一个语义,但在紧要关头,它确实起到了作用。根据定义,过于戏剧化是有问题的,如果它没有结束,一旦它被定义为过度戏剧化,它就会变得戏剧化@Motti:Bah,这只有在你相信逻辑的情况下才有问题@莫蒂:因此,这并不过分戏剧化。在这种情况下,大喊大叫“不要”是有道理的。大喊大叫“不要”有点过于戏剧化:-小心你不太想做的事情可能对人们的虚拟耳朵稍微好一点。否则我完全同意。事实上,由于它的工作原理,shared_ptr可以在向本地对象传递指针的情况下发挥作用。您可以将deleter设置为null操作,然后将其发送到下一行。你当然打破了关于共享的每一个语义,但在紧要关头,它确实起到了作用。根据定义,过于戏剧化是有问题的,如果它没有结束,一旦它被定义为过度戏剧化,它就会变得戏剧化@Motti:Bah,这只有在你相信逻辑的情况下才有问题@莫蒂:因此,这并不过分戏剧化。在这种情况下,尖叫“不要”是有道理的。