gpt4 book ai didi

c++ - 智能指针类的线程安全复制赋值运算符

转载 作者:搜寻专家 更新时间:2023-10-31 02:21:48 25 4
gpt4 key购买 nike

我正在实现一个智能指针类,但有一些困惑。如果有人能帮助我澄清,我将不胜感激。

1:我认为智能指针类在构造函数中应该有“new”,在析构函数中有“delete”。但是我似乎找不到放置“new”的地方......所以用户将负责创建新的,而智能指针类帮助清理它?

2:在设计复制赋值运算符时,一种流行的方法是copy-n-swap以保证线程安全。但是,copy-n-swap 要求对象按值(而不是按引用)传入。它还可以用于设计智能指针吗?我担心的是这是一个指针类,因此可能无法按值传入。但我对此不是很确定。

3:如果我在面试时被要求编写智能指针代码,我是否必须提供某种类型的引用计数?认为引用计数特定于 shared_ptr...

4:这一定是个愚蠢的问题,但最好先问,然后再把疑惑藏在心里。对于 SmartPointer<T>& sp访问 ptr,它应该使用 sp->ptrsp.ptr ??

感谢您的意见。

template <class T>
class SmartPointer{
T* ptr;
public:
SmartPointer():ptr(NULL){}
SmartPointer(const T& p):ptr(p){}
SmartPointer(const SmartPointer<T>& sp):ptr(sp->ptr){}
SmartPointer<T>& operator=(const SmartPointer<T>& sp);
~SmartPointer(){delete ptr;}
T& operator*(){return *ptr;}
T* operator->(){return ptr;}
};

SmartPointer& operator=(const SmartPointer& sp){
T* pOrig = ptr;
ptr = new T(sp.ptr);
delete pOrig;
return *this;
}

最佳答案

So the user will be responsible to create new, while the smart pointer class helps to clean it up?

是的,通常是这样做的。示例:

std::unique_ptr<Foo> smart_ptr(new Foo);

将构造(和分配)留给客户端的原因之一是因为 T 可以具有各种参数化构造函数。这将是棘手的,至少可以说,并且可能涉及可变参数构造函数模板和一些非常奇特的模板魔术,如果你想让一个智能指针自己构造 T 的所有可能性。在构造智能指针时让客户端传入指针更简单。只要他们在构建时立即执行此操作,它就是安全的,因为如果 operator new 在我们到达智能指针构建之前抛出,则不会分配/构建任何内容,因此不会有任何内容需要清理除了调用堆栈上已经存在的内容(为了异常安全,它应该符合 RAII)。

如果你想让它对 API 边界健壮,那么你通常想要捕获一个“删除器”,它将在生成代码的同一站点调用“operator delete”(在尝试跨模块边界工作时很重要)为模块 A 中分配的内存释放模块 B 中的内存会产生未定义的行为)。

However, copy-n-swap requires the object is passed in by value (not by reference). Can it still be used in designing a smart pointer? My concern was that this is a pointer class, hence may not be able to pass in by value. But I'm not very sure about this.

对于您制作的这种不实现引用计数的智能指针,通常最好的设计是禁止复制(赋值和复制构造函数,尽管移动构造函数很好)。

否则,您将回到转移所有权的古老做法(就像古老的 std::auto_ptr 的情况)或尝试深度复制指针对象。

转移所有权特别容易出现人为错误,因为它将复制的来源视为可变的(这是完全不寻常且令人迷惑的行为)。如果你这样做,你可以使用原子 CAS 来交换指针,但是你需要让复制构造函数和赋值运算符通过引用接受事物,而不是 const 引用或按值,因为它将把源视为可变的(要么或者使您拥有的私有(private) ptr 成员可变并使用 const 引用)。

深度复制指针对象是一种有趣的想法,但这样做的一个问题是有人可能会尝试在 T 不是完整类型(未定义,仅声明)的站点复制您的智能指针。它类似于析构函数的问题,所以如果你想像这样制作一个深度复制智能指针,一个可靠的解决方案是捕获 T 的复制构造函数(例如:将函数指针存储到你在智能指针时生成的函数被构造为克隆/复制构造 T 的新元素)。

还对您现有的深度复制代码进行了轻微修复:

SmartPointer& operator=(const SmartPointer& sp){
T* pOrig = ptr;
ptr = new T(*sp.ptr); <-- need to dereference here
delete pOrig;
return *this;
}

3: This must be a dumb question, but better ask then keep doubts inside. for SmartPointer& sp to access ptr, should it use sp->ptr or sp.ptr??

让编译器解决您的疑虑。给定一个引用,SmartPointer& spsp->ptr 在这种情况下将是一个编译器错误,除非 T 有一个名为 ptr 的成员 你可以访问,这可能不是你想要的。 sp->ptr 会调用重载的 operator->,而不是访问智能指针的实际私有(private)成员。 operator-> 通常只为指针定义,因此尝试在引用或 const 引用上使用它会调用重载的用户定义运算符。

关于c++ - 智能指针类的线程安全复制赋值运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31007070/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com