C++ 智能指针
2016-05-05 00:55
477 查看
ique_ptr is what you need, since it makes Settings the only (unique) owner of the pointed object, and the only object which is responsible for its destruction.
Under this assumption, getDevice() should return a simple observing pointer (observing pointers are pointers which do not keep the pointed object alive). The simplest kind of observing pointer is a raw pointer:
'''
};
class Settings {
std::unique_ptr device;
public:
Settings(std::unique_ptr d) {
device = std::move(d);
}
};
int main() {
std::unique_ptr device(new Device());
Settings settings(std::move(device));
// ...
Device *myDevice = settings.getDevice();
// do something with myDevice...
}
'''
[NOTE 1: You may be wondering why I am using raw pointers here, when everybody keeps telling that raw pointers are bad, unsafe, and dangerous. Actually, that is a precious warning, but it is important to put it in the correct context: raw pointers are bad when used for performing manual memory management, i.e. allocating and deallocating objects through new and delete. When used purely as a means to achieve reference semantics and pass around non-owning, observing pointers, there is nothing intrinsically dangerous in raw pointers, except maybe for the fact that one should take care not to dereference a dangling pointer. - END NOTE 1]
[NOTE 2: As it emerged in the comments, in this particular case where the ownership is unique and the owned object is always guaranteed to be present (i.e. the internal data member device is never going to be nullptr), function getDevice() could (and maybe should) return a reference rather than a pointer. While this is true, I decided to return a raw pointer here because I meant this to be a short answer that one could generalize to the case where device could be nullptr, and to show that raw pointers are OK as long as one does not use them for manual memory management. - END NOTE 2]
The situation is radically different, of course, if your Settings object should not have the exclusive ownership of the device. This could be the case, for instance, if the destruction of the Settings object should not imply the destruction of the pointed Device object as well.
This is something that only you as a designer of your program can tell; from the example you provide, it is hard for me to tell whether this is the case or not.
To help you figure it out, you may ask yourself whether there are any other objects apart from Settings that are entitled to keep the Device object alive as long as they hold a pointer to it, instead of being just passive observers. If that is indeed the case, then you need a shared ownership policy, which is what std::shared_ptr offers:
'''
};
class Settings {
std::shared_ptr device;
public:
Settings(std::shared_ptr const& d) {
device = d;
}
};
int main() {
std::shared_ptr device = std::make_shared();
Settings settings(device);
// ...
std::shared_ptr myDevice = settings.getDevice();
// do something with myDevice...
}
'''
Notice, that weak_ptr is an observing pointer, not an owning pointer - in other words, it does not keep the pointed object alive if all other owning pointers to the pointed object go out of scope.
The advantage of weak_ptr over a regular raw pointer is that you can safely tell whether weak_ptr is dangling or not (i.e. whether it is pointing to a valid object, or if the object originally pointed to has been destroyed). This can be done by calling the expired() member function on the weak_ptr object.
http://stackoverflow.com/questions/15648844/using-smart-pointers-for-class-members
Under this assumption, getDevice() should return a simple observing pointer (observing pointers are pointers which do not keep the pointed object alive). The simplest kind of observing pointer is a raw pointer:
'''
include
class Device {};
class Settings {
std::unique_ptr device;
public:
Settings(std::unique_ptr d) {
device = std::move(d);
}
Device* getDevice() { return device.get(); }
};
int main() {
std::unique_ptr device(new Device());
Settings settings(std::move(device));
// ...
Device *myDevice = settings.getDevice();
// do something with myDevice...
}
'''
[NOTE 1: You may be wondering why I am using raw pointers here, when everybody keeps telling that raw pointers are bad, unsafe, and dangerous. Actually, that is a precious warning, but it is important to put it in the correct context: raw pointers are bad when used for performing manual memory management, i.e. allocating and deallocating objects through new and delete. When used purely as a means to achieve reference semantics and pass around non-owning, observing pointers, there is nothing intrinsically dangerous in raw pointers, except maybe for the fact that one should take care not to dereference a dangling pointer. - END NOTE 1]
[NOTE 2: As it emerged in the comments, in this particular case where the ownership is unique and the owned object is always guaranteed to be present (i.e. the internal data member device is never going to be nullptr), function getDevice() could (and maybe should) return a reference rather than a pointer. While this is true, I decided to return a raw pointer here because I meant this to be a short answer that one could generalize to the case where device could be nullptr, and to show that raw pointers are OK as long as one does not use them for manual memory management. - END NOTE 2]
The situation is radically different, of course, if your Settings object should not have the exclusive ownership of the device. This could be the case, for instance, if the destruction of the Settings object should not imply the destruction of the pointed Device object as well.
This is something that only you as a designer of your program can tell; from the example you provide, it is hard for me to tell whether this is the case or not.
To help you figure it out, you may ask yourself whether there are any other objects apart from Settings that are entitled to keep the Device object alive as long as they hold a pointer to it, instead of being just passive observers. If that is indeed the case, then you need a shared ownership policy, which is what std::shared_ptr offers:
'''
include
class Device {};
class Settings {
std::shared_ptr device;
public:
Settings(std::shared_ptr const& d) {
device = d;
}
std::shared_ptr<Device> getDevice() { return device; }
};
int main() {
std::shared_ptr device = std::make_shared();
Settings settings(device);
// ...
std::shared_ptr myDevice = settings.getDevice();
// do something with myDevice...
}
'''
Notice, that weak_ptr is an observing pointer, not an owning pointer - in other words, it does not keep the pointed object alive if all other owning pointers to the pointed object go out of scope.
The advantage of weak_ptr over a regular raw pointer is that you can safely tell whether weak_ptr is dangling or not (i.e. whether it is pointing to a valid object, or if the object originally pointed to has been destroyed). This can be done by calling the expired() member function on the weak_ptr object.
http://stackoverflow.com/questions/15648844/using-smart-pointers-for-class-members
相关文章推荐
- C++动态链接库编程深入浅出
- More Effective C++----(8)理解各种不同含义的new和delete
- C++实验5-数组分离
- C++之类模板
- vc++编译连接原理与过程
- c++实现日期类,日历计算器
- 快速排序的c语言实现代码
- c++ 调用dll
- More Effective C++----(7)不要重载"&&"、"||"、","
- C语言中如何避免野指针
- 64位与32位编程的数据类型区别(C/C++)
- PC-lint 简明教程(C/C++静态代码检查工具)
- 工厂模式-c++实现
- More Effective C++----(6)自增、自减操作符前缀形式和后缀形式的区别
- c++第5次上机-1
- C语言位运算
- C++两个栈实现一个队列和两个队列实现一个栈
- 【学习C++】3.构造函数
- C++ 模板详解(二)
- C++ 模板详解(一)