C++ 为什么没有"?;“弱指针”;对于原始指针?还是有?
毫无疑问,共享指针是个好主意。但只要大型程序包含原始指针,我认为使用共享指针就有很大的风险。主要是,您将失去对指向包含原始指针的对象的指针的实际生命周期的控制,错误将发生在更难找到和调试的位置 我的问题是,没有尝试添加到现代C++中的“弱指针”,它不依赖于使用共享指针吗?我的意思是,只要在程序的任何部分删除一个指针,它就会变成NULL。有没有理由不使用这种自制包装 为了更好地解释我的意思,下面是我做的一个“弱指针”。我把它命名为WatchedPtrC++ 为什么没有"?;“弱指针”;对于原始指针?还是有?,c++,c++11,smart-pointers,C++,C++11,Smart Pointers,毫无疑问,共享指针是个好主意。但只要大型程序包含原始指针,我认为使用共享指针就有很大的风险。主要是,您将失去对指向包含原始指针的对象的指针的实际生命周期的控制,错误将发生在更难找到和调试的位置 我的问题是,没有尝试添加到现代C++中的“弱指针”,它不依赖于使用共享指针吗?我的意思是,只要在程序的任何部分删除一个指针,它就会变成NULL。有没有理由不使用这种自制包装 为了更好地解释我的意思,下面是我做的一个“弱指针”。我把它命名为WatchedPtr #include <memory>
#include <memory>
#include <iostream>
template <typename T>
class WatchedPtr {
public:
// the only way to allocate new pointer
template <typename... ARGS>
WatchedPtr(ARGS... args) : _ptr (new T(args...)), _allocated (std::make_shared<bool>(true)) {}
WatchedPtr(const WatchedPtr<T>& other) : _ptr (other._ptr), _allocated (other._allocated) {}
// delete the pointer
void del () {delete _ptr; *_allocated = false;}
auto& operator=(const WatchedPtr<T> &other) { return *this = other; }
bool isNull() const { return *_allocated; }
T* operator->() const { return _ptr; }
T& operator*() const { return *_ptr; }
private:
T* _ptr;
std::shared_ptr <bool> _allocated;
};
struct S {
int a = 1;
};
int main () {
WatchedPtr<S> p1;
WatchedPtr<S> p2(p1);
p1->a = 8;
std::cout << p1.isNull () << std::endl;
std::cout << p2.isNull () << std::endl;
p2.del ();
std::cout << p1.isNull () << std::endl;
std::cout << p1.isNull () << std::endl;
return 0;
}
-已编辑-
谢谢大家。在迄今为止的评论和回答之后,有一些澄清:
- 我为WatchedPtr提供的实现仅仅是为了演示我的意思:一个指针不能从外部分配中获取副本,不能从外部删除,如果被删除,它将变为null。这一实现显然远远不够完美,也不是为了完美
- 共享_ptr和原始指针混合使用的问题非常常见:A*作为原始指针保存,因此在程序的某个点创建,并在程序的某个点显式删除。B持有a*,B*作为共享的ptr持有,因此B*的寿命模糊。因此,在删除B持有的A*之后,B可能会长寿
- 在我看来,“WatchedPtr”的主要用法是防御性编程。i、 e.检查空值,并尽可能确保连续性(以及调试错误)。共享ptr可以做到这一点,但它会以一种非常危险的方式隐藏和延迟问题
- “WatchedPtr”(非常少且明确的“所有者”)也可以有设计用途,但这不是主要思想。因此,共享指针确实在起作用
- “WatchedPtr”的目的不是一次替换程序中所有现有的原始指针。这与替换为shared_ptr的工作不同,IMHO一次就完成了整个程序。这对于大型项目来说是不现实的
- 弱指针依赖于来自智能指针基础结构的通知,因此您永远无法使用实际的原始指针来实现这一点
我们可以想象,
unique_ptr
的扩展,它当然支持弱指针。大概没有人急于执行这样一个特性的主要原因是弱指针已经在“使用重命名,一切都应该工作”的规模结束,而<>代码> UnQuyGPPT//Cube >是在“管理您的生命通过RAII或您不是真正的C++程序员”的规模结束。弱指针还要求每个分配有一个单独的控制块,这意味着这种监视ptr
的性能优势与共享ptr
相比是最小的
我认为使用共享指针有很大的风险。主要是,您将失去对指向包含原始指针的对象的指针的实际生命周期的控制,错误将发生在更难找到和调试的位置
那么你说
只是一个指针,当在程序的任何部分删除时,它将变为NULL
你没看到矛盾吗
您不想使用共享指针,因为对象的生存期是在运行时确定的。到目前为止还不错
但是,您希望指针在所有者删除它时自动变为空。问题是,如果指针的生命周期已知,则根本不需要它!如果您知道指针的生命周期何时结束,那么您应该能够删除该指针的所有实例,并且有一个方法来检查指针是否已死亡
如果你有一个指针,你不知道它的所有者何时会释放它,并且没有办法检查或者对弱所有者的观点没有明显的副作用,那么你真的可以控制指针的生命周期吗?不是真的
实际上,您的实现依赖于包含一个共享指针。这在某种意义上是很有启发性的,您需要某种形式的共享所有权才能实现一个原始指针,而这个原始指针可能有弱指针指向它。然后,如果您需要共享所有权来实现具有弱引用的原始指针,那么您将得到一个共享指针。这就是为什么你提议的类的存在是矛盾的
std::shared_ptr
+std::weak_ptr
用于处理“程序的某些部分不知道所有者何时释放资源”的问题。您需要的是一个std::shared_ptr
和多个std::weak_ptr
,以便它们知道何时释放资源。这些类具有在运行时检查变量生存期所需的信息
或者,如果相反,您知道指针的生命周期,那么使用这些知识,找到一种方法来删除悬挂指针,或者公开一种方法来检查悬挂指针。阅读答案和注释,以及,我得到了以下答案:
遵循指南时,不需要包含“新建”和“删除”的“监视PTR”。然而,出于调试/质量保证的目的,跟踪从智能指针获取的原始指针的有效性的方法对我来说仍然是个问题 详情如下: 应继续使用原始指针。由于各种原因。但是,不应明确“新建”和“删除”。调用“新建”和“删除”的情况都应替换为共享\u ptr/唯一\u ptr。
在当前分配原始指针的位置,没有必要将其替换为“WatchedPtr”。
如果将原始指针替换为分配给它的其他对象,在大多数情况下,它将指向unique_ptr,而在其他情况下,它将指向shared_ptr。“WatchedPtr”(如果有的话)将从此点继续,从共享/唯一
1
1
0
0