c + +不允许栈实例,但允许新删除

问题描述:

基本上我想要的是:c + +不允许栈实例,但允许新删除

class MyClass{ 
    public: 
     MyClass() = default; 
    // what should I do? 
} 

MyClass mc; // compile time error; 
auto pmc = new MyClass; //OK 
delete pmc; //OK too 

我知道我可以把它堆只能通过隐藏的构造函数(不能现在新的类外)或隐藏的析构函数(现在不能在课程外部删除)或隐藏两者。如果我不想介绍一些新的命名功能,只想要新的旧的删除功能,该怎么办?是否有可能(即使有黑客)?

+4

没有,只是写一个函数。 –

+0

请**编辑您的问题**,解释为什么要禁止“MyClass”堆栈自动变量并给出更有动机的示例 –

+0

我希望'new'运算符可以重载,以便它可以返回类,并且可以接受任意数量的参数,就像构造函数一样,这样我们就可以编写像:'auto px = new X(arg0,arg2,arg3);'....和'delete'就像析构函数。 – Nawaz

我 “就像一个智能指针,而不是” 的想法:

#include <iostream> 

class MyClass_ { 
    private: 
    /**/  MyClass_(void) { } 
    /**/ ~MyClass_(void) { } 
    public: 
    void  func(void) const { std::cout << "Hello" << std::endl; } 

    friend class MyClass; 
} ; 

class MyClass { 
    public: 
    /**/  MyClass(void) : p(new MyClass_) { } 
    /**/ ~MyClass(void) { delete p; } 

    // Tricky implementation details follow... 
    // The question in all cases is, who owns the MyClass_ that has been 
    // allocated on the heap? Do you always allocate a new one, and then 
    // copy the guts? (That might be expensive!) Do you change ownership? 
    // Then what about the other MyClass? What does it point to? 
    // Or do you share ownership? Then you need to ref-count so you don't 
    // delete too soon. (And this whole thing turns into an ordinary 
    // shared_ptr<MyClass_>) 

    /**/  MyClass(const MyClass &o) { } 
    /**/  MyClass(MyClass &&o) { } 
    MyClass &operator=(const MyClass &o) { } 
    MyClass &operator=(MyClass &&o) { } 

    MyClass_ * operator->(void) { return p; } 
    const MyClass_ * operator->(void) const { return p; } 

    private: 
    MyClass_ *p; 
} ; 

int 
main(int, char **) 
{ 
    MyClass a;     // this will be destroyed properly 
    MyClass *b = new MyClass; // this will leak if you don't delete it 

    a->func(); 
    (*b)->func(); 

    return 0; 
} 
+3

这很聪明。它说明了这个类只能在堆上生活的事实实际上并不是用户需要意识到的。他们关心的是实例化一个对象。通过隐藏堆分配作为实现细节,如果需要,还可以保留包装器对象的值语义。 – ComicSansMS

+1

要么正确执行五项规则,要么包括需要完成的评论(或删除它们)。否则,在复制对象时会出现未定义的行为。 – Rakete1111

+1

^那。如果你不打算写他们,至少要提到他们 –

这听起来像不是你想要的,而是将它包围在另一个类中。通过这种方式,您可以强制将存储分配到堆中,并将这些细节远离API用户。

+0

你能否提供代码和更清晰的解释......围绕着,你的意思是让它成为嵌套类吗?它将如何帮助? – Phil1970

通常的方法是让你的构造函数private,并添加一些static成员函数(你可以称之为工厂或制作函数)返回一个指针。

,以便类会是什么样子

class MyClass{ 
    private: 
     MyClass() = default; 
    public: 
     static MyClass* make() { return new MyClass; }; 
    // what should I do? 
} 

,你会代码:

auto mc = MyClass::make(); 

其他地方(的new MyClass代替)

等,但要注意的rule of five,并考虑使用(作为MyClass::make的返回类型)<memory> header中的一些smart pointer

你也可以拥有自己的一元operator ->operator *和自己variadic templates通过std::make_shared灵感定义自己的智能指针类...

只想好老new和delete

在真正的C++ 11中,这是令人不悦的,可能被认为是糟糕的风格。你应该避免在库外使用明确的new,并采用一些智能指针的编码方式。

+0

你可以使用智能指针的想法,而不是引用计数对象,你只是使用指针来确保所有的底层对象都分配在堆上。 (指针本身可以被分配或自动分配,这并不重要。) –