C++ 通过传递外部指针或内部调用new构造的类,是否可以在销毁时天真地删除此指针?

C++ 通过传递外部指针或内部调用new构造的类,是否可以在销毁时天真地删除此指针?,c++,memory,dynamic,delete-operator,C++,Memory,Dynamic,Delete Operator,我有一个类A,它有一个指向类B的指针作为它的一个字段: class A { private: B *ptr; public: A(B*); A(); ~A(); } A::A(B *ptr) { this->ptr = ptr; } A::A() { this->ptr = new B(); } A::~A() { delete this->ptr; } 我希望析构函数只在由new分配的情况下删除B,我只能通过设置

我有一个类A,它有一个指向类B的指针作为它的一个字段:

class A {
private:
    B *ptr;
public:
    A(B*);
    A();
    ~A();
}

A::A(B *ptr)
{
    this->ptr = ptr;
}

A::A()
{
    this->ptr = new B();
}

A::~A()
{
    delete this->ptr;
}
我希望析构函数只在由new分配的情况下删除B,我只能通过设置一个标记来存储指针的原点(这样,只有在构建a的过程中分配了ptr时才会调用delete),或者是否有更优雅的解决方案,也就是,我可以在任何指针上调用delete(我知道,如果传入的指针是使用new分配的,那么它也将被删除,但是如果指针是从调用A的构造函数的作用域传入的,那么显然删除它是未定义的)

还是有更优雅的解决方案

不,不是真的;它需要清楚地记录谁拥有这个指针。它看起来像你的类,所以你能自己构造
ptr

#include <memory>

class A {
private:
    std::unique_ptr<B> ptr;
public:
    A(some_data args) 
        : ptr(new B(args)) { };
    A();    
}
#包括
甲级{
私人:
std::唯一的ptr ptr;
公众:
A(一些_数据参数)
:ptr(新B(args)){};
A();
}
如果您的类不拥有也可以的指针,就不要取消分配它。否则您将需要在外部设置一个标志(即,
deallocu on_destruct
)来知道该做什么,这可能会变得混乱

还是有更优雅的解决方案

不,不是真的;它需要清楚地记录谁拥有这个指针。它看起来像你的类,所以你能自己构造
ptr

#include <memory>

class A {
private:
    std::unique_ptr<B> ptr;
public:
    A(some_data args) 
        : ptr(new B(args)) { };
    A();    
}
#包括
甲级{
私人:
std::唯一的ptr ptr;
公众:
A(一些_数据参数)
:ptr(新B(args)){};
A();
}

如果您的类不拥有也可以的指针,就不要取消分配它。否则您将需要在外部设置一个标志(即,
dealloc\u on\u destruct
)要知道该做什么,这可能会变得混乱。

更优雅的解决方案是不让类拥有不同的所有权模型,在这种情况下,是由类拥有还是不由类拥有。不要将这两种想法混合在同一类类型中,因为这只会混淆用户/客户机(违反了最小惊喜原则)


创建具有所需不同行为的单独类,或者选择一个所有权模型并强制客户机坚持使用它(在非默认构造函数中传入并转移所有权,或者不允许自分配).

更优雅的解决方案是不要让类拥有不同的所有权模型,在这种情况下,是由类拥有还是不由类拥有。不要将这两种想法混合在同一类类型中,因为这只会混淆用户/客户机(违反最小意外原则)


创建具有所需不同行为的单独类,或者选择一个所有权模型并强制客户机坚持使用它(在非默认构造函数中传入并转移所有权,或者不允许自分配).

仅凭您提供的代码无法回答这个问题。真正的问题是为什么您可以接受或不接受指针,以及如果指针传递给您,谁拥有内存

根据您的对象在特定域中应该做什么,可以采取不同的替代方案。例如,如果您可以与调用者共享所有权,那么您应该采取
共享的\u ptr
,如果您要保留对象的所有权,则应使用
唯一的\u ptr
在int中明确说明如果您的对象将要获得所有权,如果所有权不被共享,那么考虑将引用传递给对象(即使您在内部存储指针),在这种情况下,您可以将所有权与实际使用分开:

// option 1: shared ownwership
class A {
   std::shared_ptr<B> ptr;
public:
   A( std::shared_ptr<B> const & p ) : ptr(p) {}
   A() : ptr( std::make_shared<B>() ) {}
};
// option 2: grab ownership
class A {
   std::unique_ptr<B> ptr;
public:
   A( std::unique_ptr<B> p ) : ptr( std::move(p) ) {}
   A() : ptr( new B(); }
};
// option 3: no ownership (unless we create the object)
// (separating concerns: ref to access the object, ptr to manage it)
class A {
   std::unique_ptr<B> ptr;   // only ownership
   B * ref;
public:
   A( B & b ) : ptr(), ref(&b) {}
   A() : ptr( new B() ), ref(ptr.get()) {}
   // Internally use 'ref' to access the object the destructor will delete it 
   // if needed
};
//选项1:共享所有权
甲级{
std::共享的ptr;
公众:
A(std::shared_ptr const&p):ptr(p){
A():ptr(std::make_shared()){}
};
//选择2:攫取所有权
甲级{
std::唯一的ptr ptr;
公众:
A(std::unique_ptr p):ptr(std::move(p)){
A():ptr(新的B();}
};
//选项3:无所有权(除非我们创建对象)
//(分离关注点:ref访问对象,ptr管理对象)
甲级{
std::unique_ptr ptr;//仅所有权
B*ref;
公众:
A(B&B):ptr(),ref(&B){}
A():ptr(新B()),ref(ptr.get()){}
//在内部使用“ref”访问对象,析构函数将删除该对象
//如果需要
};

仅凭您提供的代码无法回答这个问题。真正的问题是为什么您可以接受或不接受指针,以及如果指针传递给您,谁拥有内存

根据您的对象在特定域中应该做什么,可以采取不同的替代方案。例如,如果您可以与调用者共享所有权,那么您应该采取
共享的\u ptr
,如果您要保留对象的所有权,则应使用
唯一的\u ptr
在int中明确说明如果您的对象将要获得所有权,如果所有权不被共享,那么考虑将引用传递给对象(即使您在内部存储指针),在这种情况下,您可以将所有权与实际使用分开:

// option 1: shared ownwership
class A {
   std::shared_ptr<B> ptr;
public:
   A( std::shared_ptr<B> const & p ) : ptr(p) {}
   A() : ptr( std::make_shared<B>() ) {}
};
// option 2: grab ownership
class A {
   std::unique_ptr<B> ptr;
public:
   A( std::unique_ptr<B> p ) : ptr( std::move(p) ) {}
   A() : ptr( new B(); }
};
// option 3: no ownership (unless we create the object)
// (separating concerns: ref to access the object, ptr to manage it)
class A {
   std::unique_ptr<B> ptr;   // only ownership
   B * ref;
public:
   A( B & b ) : ptr(), ref(&b) {}
   A() : ptr( new B() ), ref(ptr.get()) {}
   // Internally use 'ref' to access the object the destructor will delete it 
   // if needed
};
//选项1:共享所有权
甲级{
std::共享的ptr;
公众:
A(std::shared_ptr const&p):ptr(p){
A():ptr(std::make_shared()){}
};
//选择2:攫取所有权
甲级{
std::唯一的ptr ptr;
公众:
A(std::unique_ptr p):ptr(std::move(p)){
A():ptr(新的B();}
};
//选项3:无所有权(除非我们创建对象)
//(分离关注点:ref访问对象,ptr管理对象)
甲级{
std::unique_ptr ptr;//仅所有权
B*ref;
公众:
A(B&B):ptr(),ref(&B){}
A():ptr(新B()),ref(ptr.get()){}
//在内部使用“ref”访问对象,析构函数将删除该对象
//如果需要
};

除了其他人所说的(避免这种设计):如果