我从未使用任何类型的智能指针,但是当主题是指针时,我几乎无处不在地阅读它们。我知道有些情况下智能指针比原始指针更好用,因为在某种程度上它们可以管理指针的所有权。但是,我仍然不知道,&#34之间的界限在哪里?我不需要智能指针"和#34;这是智能指针的情况"。
让我们说,我有以下情况:
class A {
public:
double get1(){return 1;}
double get2(){return 2;}
};
class SomeUtilityClass {
public:
SomeUtilityClass(A* a) : a(a) {}
double getResult(){return a->get1() + a->get2();}
void setA(A* a){a = a;}
private:
A* a;
};
int main(int argc, char** argv) {
A a;
SomeUtilityClass u(&a);
std::cout << u.getResult() << std::endl;
A a2;
u.setA(&a2);
std::cout << u.getResult() << std::endl;
return 0;
}
这当然是一个过于简单的例子。我的意思是SomeUtilityClass
不应该&#34;拥有&#34; A
的实例(因为它只是一个实用程序类),因此它只保存一个指针。
关于指针,我所知道的唯一可能出错的是:
SomeUtilityClass
可以使用空指针SomeUtilityClass
没有注意到它智能指针如何帮助避免此问题?在这种情况下使用智能指针可以获得哪些其他好处?
PS:我知道智能指针有几个问题(例如this one)。但是,如果您能告诉我有关此特定示例的影响,我将不胜感激。
答案 0 :(得分:2)
这取决于参数的创建和存储方式。如果您不拥有内存并且可以静态或动态分配,则原始指针是一个非常合理的解决方案 - 特别是如果您需要支持交换数据,如示例中所示。另一个选择是使用std::reference_wrapper
,这将解决您的nullptr
问题,同时保持相同的语义。
如果您持有指向某个共享资源的指针(即存储在std::shared_ptr
某处)并希望能够检查它是否已被删除,则可以保留std::weak_ptr
。
答案 1 :(得分:1)
如果SomeUtilityClass
不拥有成员变量a
,则智能指针没有意义。
您可以考虑一个引用成员,它将删除空指针的问题。
答案 2 :(得分:1)
在C ++中表达非拥有指针的默认方式是weak_ptr
。要使用weak_ptr
,您需要使用shared_ptr
获取所有权,因此在您的示例中,您将使用
shared_ptr<A> owner(...)
而不是
A a
然后作为SomeUtilityClass
的私有指针成员使用弱指针:
weak_ptr<A> w;
并使用shared_ptr
初始化它:
SomeUtilityClass(shared_ptr<A> o) : w(o) {}
但是,您无法直接使用weak_ptr
,因为shared_ptr
可能会超出范围而您的弱指针不再指向任何内容。使用前你需要锁定它:
shared_ptr<A> locked = w.lock();
如果拥有指针不再管理对象,则locked
指针将为空,例如它超出了范围。如果它不是空的,你可以使用它然后它将超出范围自动释放锁定对象。
{+ 1}}和shared_ptr
在C ++ 11的标准库中都可用,在Boost中可用于较旧的编译器。
答案 3 :(得分:0)
有不同类型的智能指针。在你的情况下,显然不需要智能指针,但它仍然可以提供一些好处。
可以使用空指针
实例化SomeUtilityClass
当你得到一个NULL指针作为参数时,最好通过检查构造函数,抛出异常或以其他方式指示错误来解决这个问题。我很难想象智能指针如何帮助,除非你使用一个不接受NULL的特定智能指针类,所以它已经为你做了检查。
指向的对象可能被删除/超出范围,没有 SomeUtilityClass注意到它
实际上可以使用特殊类型的智能指针来解析这个,但是需要指向的对象以某种方式支持销毁通知。一个这样的例子是Qt库中的QPointer
类,它只能指向QObject
个实例,它们在删除时会通知它,因此当删除对象时,智能指针会自动变为NULL。但是,这种方法存在一些问题:
MyClass
,扩展执行删除通知的类(Qt案例中为QObject
),则会得到奇怪的结果:它是QObject的析构函数,通知智能指针,所以当MyClass
析构函数已经开始它的脏工作时你有可能访问它,所以对象被部分破坏,但是指针尚未归零,因为破坏仍在进行中。