Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.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++ 有没有办法强制使用shared_ptr在堆上创建对象?_C++_C++11_Stl_Heap - Fatal编程技术网

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

C++ 有没有办法强制使用shared_ptr在堆上创建对象?,c++,c++11,stl,heap,C++,C++11,Stl,Heap,我想知道是否有可能通过创建私有/受保护的描述器和使用共享的描述器来同时确保自动资源管理(共享描述器的RAII功能),强制在堆上创建对象。 也许可以用另一种方式吗? 我问这个问题的原因是,从我在STL听到的(我还没看)来看,没有虚拟的描述器,所以除了…共享的ptr之外,没有办法确保安全销毁? 如果是这样的话,就没有办法将对象强制到堆中,因为shared_ptr正在尝试访问Destructor。 无论如何,要绕过这些限制?C++是一种将代码的正确性掌握在程序员手中的语言。试图通过一些复杂的方法来改变

我想知道是否有可能通过创建私有/受保护的描述器和使用共享的描述器来同时确保自动资源管理(共享描述器的RAII功能),强制在堆上创建对象。 也许可以用另一种方式吗? 我问这个问题的原因是,从我在STL听到的(我还没看)来看,没有虚拟的描述器,所以除了…共享的ptr之外,没有办法确保安全销毁? 如果是这样的话,就没有办法将对象强制到堆中,因为shared_ptr正在尝试访问Destructor。
无论如何,要绕过这些限制?

C++是一种将代码的正确性掌握在程序员手中的语言。试图通过一些复杂的方法来改变这一点通常会导致代码难以使用或工作不太好。强迫程序员在堆上创建一个对象,即使这对于特定的情况不是“正确的”,这是很糟糕的。如果程序员愿意,就让他/她射中自己的脚吧

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

我不完全确定“虚拟析构函数”与“安全销毁”和“共享指针”的关系——这是三个不同的概念,它们之间的关系不是很密切——当一个类被用作基类来派生一个新类时,需要虚拟析构函数。STL对象不是从中派生出来的[通常,您使用模板或继承,尽管它们可以组合,但这样做很快就会变得非常复杂],因此在STL中不需要使用虚拟析构函数

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

我认为“安全销毁”意味着“无内存泄漏”[而不是“正确销毁”,这当然也可能是一个问题,并导致内存泄漏问题]。对于很多情况,这意味着“首先不要使用指向对象的指针”。我在这里看到很多例子,程序员毫无理由地调用
new
<代码>矢量*v=新矢量绝对是一种“臭味”(就像鱼或肉一样,如果臭味很重,代码就有问题)。如果您正在调用new,那么使用共享指针、惟一指针或其他一些“包装”是一个好主意。但是你不应该强迫这个概念——有时候有很好的理由不这样做

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

既然我已经告诉过你不要这样做,这里有一个方法可以实现它:

class X
{
    private:
       int x; 
       X() : x(42) {}; 
    public:
       static shared_ptr<X> makeX() { return make_shared<X>(); }
};
X类
{
私人:
int x;
X():X(42){};
公众:
静态共享的_ptrmakex(){return make_shared();}
};
由于构造函数是私有的,类的“用户”不能调用“new”或创建此类对象。[您可能还希望将复制构造函数和赋值运算符置于私有状态,或者使用
delete
来防止它们被使用]

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

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

X类
{
私人:
int x;
X():X(42){};
公众:
静态std::shared_ptr makeX()
{
返回std::shared_ptr(新的X());
}
};

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

我不理解你对这个问题的解释。你能更准确地解释一下你想要什么吗?好吧,让我们来讨论一个假设的例子,假设我想要创建一个类树,并强制这些类的任何用户只在堆上创建对象。因此,只需将描述设置为私有/受保护即可。现在,如果对象超出范围,它将被取消定向,但是如果有一个类树,并且析构函数不是虚拟的,它将无法很好地取消定向。因此,假设我无法使用虚拟机,无论出于何种原因,我如何正确地销毁这些对象?@LifePhilPsyPro这听起来是个错误的问题。请务必使用
virtual
,因为这是正确的解决方案。或者,不要将继承与基类指针一起使用,这样就不需要虚拟析构函数。@LifePhilPsyPro:等等,如果我理解正确,您是否从STL类派生类,如
std::vector
?这就是这些问题的根源吗?事实上,没有什么“实际”问题比理论问题更重要。我试图找出我能做什么,不能做什么C++提供给我。因此,我实际上没有陷入一种必须使用我所描述的东西的情况。我只是在想,如果是偶数的话,如何同时使用智能指针进行RAII和强制堆分配。我不知道什么时候,为什么我需要它。但我认为这是很有用的。如果您只使用共享指针管理对象,那么实际上不需要虚拟析构函数。只要第一个共享指针是用一个指向最派生类型的指针初始化的(按照您的示例,它将是这样),删除程序就会做正确的事情。在某些情况下,它可能是可行的,例如,如果类派生自
std::enable\u shared\u from\u this
make\u shared
调用将失败,因为make\u shared没有访问私有构造函数的权限。这种模式不受欢迎的另一个原因是,您可以通过添加一个公共构造函数来解决这个问题,该构造函数需要一个只有X才能构造的令牌,并将其传递给
make\u shared