for*_*818 8 c++ pointers smart-pointers
我从来没有使用任何类型的智能指针,但当主题是指针时,我几乎无处不在地阅读它们.我知道有些情况下智能指针比原始指针更好用,因为在某种程度上它们可以管理指针的所有权.但是,我仍然不知道,"我不需要智能指针"和"这是智能指针的情况"之间的界限.
可以说,我有以下情况:
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;
}
Run Code Online (Sandbox Code Playgroud)
这当然是一个过于简单的例子.我的意思是SomeUtilityClass不应该"拥有"一个实例A(因为它只是一个实用类),因此它只是一个指针.
关于指针,我所知道的唯一可能出错的是:
SomeUtilityClass 可以使用空指针进行实例化SomeUtilityClass注意到它智能指针如何帮助避免这个问题?在这种情况下,使用智能指针可以获得哪些其他好处?
PS:我知道智能指针有几个问题(例如这个).但是,如果您能告诉我有关此特定示例的影响,我将不胜感激.
为了这个答案的目的,我将 setA 重新定义为:
void setA(A* new_a){a = new_a;}
Run Code Online (Sandbox Code Playgroud)
考虑:
// Using your SomeUtilityClass
int main() {
A a;
SomeUtilityClass u(&a);
// We define a new scope, just because:
{
A b;
u.setA(&b);
}
std::cout << u.getResult() << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
作用域完成后,SomeUtilityClass有一个悬空指针并getResult()调用未定义行为。请注意,这不能通过引用来解决:您仍然会得到一个悬空的引用。
现在考虑使用智能指针的版本:
class SomeUtilityClass {
public:
SomeUtilityClass(std::shared_ptr<A>& a) : a{a} {}
double getResult(){return a->get1() + a->get2();}
void setA(std::shared_ptr<A>& new_a){a = new_a;}
private:
std::shared_ptr<A> a;
};
int main() {
std::shared_ptr<A> a{new A};
SomeUtilityClass u{a};
// We define a new scope, just because:
{
std::shared_ptr<A> b{new A};
u.setA(b);
}
std::cout << u.getResult() << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因为您拥有共享所有权,所以无法获得悬空指针。所指向的内存b将像往常一样被删除,但只有在u被销毁(或其指针被更改)之后。
恕我直言,在大多数情况下,您应该使用智能指针(即使一开始它似乎没有多大意义)。它使维护变得更加容易。仅在实际需要它们的特定代码中使用原始指针,并尽可能封装/隔离该代码。