有没有办法强制使用shared_ptr在堆上创建对象?

时间:2013-08-03 13:34:52

标签: c++ c++11 stl heap

我想知道是否可以通过创建私有/受保护的desctuctor并使用shared_ptrs同时确保自动资源管理(shared_ptr的RAII功能)来强制在堆上创建对象。 可以用不同的方式完成吗? 我之所以这样说,是因为我从STL那里听到的(没看过),没有虚拟的解决方案,所以除了... shared_ptr之外没有办法确保安全销毁? 如果是这样,由于shared_ptr尝试访问destuctor,因此无法将对象强制转移到堆中。 无论如何要绕过这些限制?

2 个答案:

答案 0 :(得分:3)

C ++是一种将代码的正确性放在程序员手中的语言。试图通过一些复杂的方法来改变它通常会导致代码难以使用或不能很好地工作。强迫程序员的手,以便他必须在堆上创建一个对象,即使这对于那个特定情况不是“正确”也是坏事。如果他愿意,让程序员用脚射击他/她自己。

在较大的项目中,代码应由同行(最好至少有时由更高级的员工)审查,以确保其正确性,并遵循项目的编码指南。

我不完全确定“虚拟析构函数”与“安全破坏”和“共享指针”的关系 - 这三个不同的概念并不是非常密切相关的 - 当一个类用作基础时需要虚拟析构函数-class派生一个新类。 STL对象并不意味着从[通常使用模板或继承,虽然它们可以组合,但是当你这样做时会非常复杂],因此不需要在STL中使用虚拟析构函数。

如果你有一个基类的类,并且存储是基于指针或对基类的引用完成的,那么你必须有虚拟析构函数 - 或者不使用继承。

“安全销毁”,我接受它,意味着“没有内存泄漏”[而不是“正确的破坏”,这当然也可能是一个问题 - 并导致内存泄漏问题]。对于大量情况,这意味着“首先不要使用指向对象的指针”。我在这里看到了很多关于程序员正在调用new的地方的例子,绝对没有理由。 vector<X>* v = new vector<X>;绝对是一种“难闻的气味”(就像鱼或肉一样,如果它闻起来很糟糕,代码有问题)。如果你正在调用new,那么使用共享指针,唯一指针或其他一些“包装”是一个好主意。但是你不应该强迫这个概念 - 偶尔有充分的理由不这样做。

“共享指针”是“在不再使用时自动销毁对象”的概念,这是一种避免内存泄漏的有用技术。

现在我告诉你不要这样做,这是实现它的一种方法:

class X
{
    private:
       int x; 
       X() : x(42) {}; 
    public:
       static shared_ptr<X> makeX() { return make_shared<X>(); }
};

由于构造函数是私有的,因此类的“用户”不能调用“new”或创建此类对象。 [您可能还希望将复制构造函数和赋值运算符设置为私有或使用delete来防止它们被使用]。

然而,我仍然认为这首先是一个坏主意。

答案 1 :(得分:0)

Mats的回答确实是错误的。 make_shared需要一个公共构造函数。 但是,以下内容有效:

class X
{
private:
    int x;

    X() : x( 42 ) {};
public:

    static std::shared_ptr<X> makeX()
    {
        return std::shared_ptr<X>( new X() );
    }
};

我不喜欢使用new关键字,但是在这种情况下,这是唯一的方法。