Ref: https://zhuanlan.zhihu.com/p/71649913
[ 这部分仅关于:shared_ptr ]
vector销毁,vector中的指针们所指向的各自“空间“也需要销毁。
vector的某个指针改变,相联系的指针内容全部改变。
// util/sharedptr1.cpp #include <iostream> #include <string> #include <vector> #include <memory> using namespace std; int main() { // two shared pointers representing two persons by their name shared_ptr<string> pNico(new string("nico")); shared_ptr<string> pJutta(new string("jutta")); // capitalize person names (*pNico)[0] = ’N’; pJutta->replace(0,1,"J"); // put them multiple times in a container vector<shared_ptr<string>> whoMadeCoffee; whoMadeCoffee.push_back(pJutta); whoMadeCoffee.push_back(pJutta); whoMadeCoffee.push_back(pNico); whoMadeCoffee.push_back(pJutta); whoMadeCoffee.push_back(pNico); // print all elements for (auto ptr : whoMadeCoffee) { cout << *ptr << " "; } cout << endl; // overwrite a name again *pNico = "Nicolai"; // print all elements again for (auto ptr : whoMadeCoffee) { cout << *ptr << " "; } cout << endl; // print some internal data cout << "use_count: " << whoMadeCoffee[0].use_count() << endl; }
如果某个指针要放弃某一块内存时,使用 lambda 作为构造函数的第二个参数,定义销毁操作。
当对象的最后一个指针被调用时,lambda被调用。
shared_ptr<string> pNico(new string("nico"), [](string* p) { cout << "delete " << *p << endl; delete p; } ); ... pNico = nullptr; // pNico does not refer to the string any longer whoMadeCoffee.resize(2); // all copies of the string in pNico are destroyed
默认的销毁行为不会执行delete[],所以要自己定义销毁行为,例如:
std::shared_ptr<int> p(new int[10], [](int* p) { delete[] p; // <---- lambda } );
另一种方式也可以:
std::shared_ptr<int> p(new int[10], std::default_delete<int[]>());
处理清理内存以外,还有其他的资源需要处理,以下是一个清理临时文件的示例:
共享指针,指向 ”输出流“ 这个 ”对象“。
#include <string> #include <fstream> // for ofstream #include <memory> // for shared_ptr #include <cstdio> // for remove()
class FileDeleter { private: std::string filename;
public: FileDeleter (const std::string& fn): filename(fn) {
}
void operator () (std::ofstream* fp) { fp->close(); // close.file std::remove(filename.c_str()); // delete file } };
int main() { // create and open temporary file: std::shared_ptr<std::ofstream> fp( new std::ofstream("tmpfile.txt"), FileDeleter("tmpfile.txt") ); ... }
shm_unlink主要用于linux Posix模式共享内存中的删除共享内存。
// util/sharedptr3.cpp #include <memory> // for shared_ptr #include <sys/mman.h> // for shared memory #include <fcntl.h> #include <unistd.h> #include <cstring> // for strerror() #include <cerrno> // for errno #include <string> #include <iostream>
class SharedMemoryDetacher { public: void operator () (int* p) { std::cout << "unlink /tmp1234" << std::endl; if (shm_unlink("/tmp1234") != 0) { std::cerr << "OOPS: shm_unlink() failed" << std::endl; } } };
std::shared_ptr<int> getSharedIntMemory(int num) { void* mem;
int shmfd = shm_open("/tmp1234", O_CREAT|O_RDWR, S_IRWXU|S_IRWXG); if (shmfd < 0) { throw std::string(strerror(errno)); } if (ftruncate(shmfd, num*sizeof(int)) == -1) { throw std::string(strerror(errno)); }
mem = mmap(nullptr, num*sizeof(int), PROT_READ|PROT_WRITE, MAP_SHARED, shmfd, 0); if (mem == MAP_FAILED) { throw std::string(strerror(errno)); } return std::shared_ptr<int>(static_cast<int*>(mem), SharedMemoryDetacher()); }
int main() { // get and attach shared memory for 100 ints: std::shared_ptr<int> smp(getSharedIntMemory(100));
// init the shared memory for (int i = 0; i < 100; ++i) { smp.get()[i] = i*42; }
// deal with shared memory somewhere else: ... std::cout << "<return>" << std::endl; std::cin.get();
// release shared memory here: smp.reset(); ... }
当然还有一种更加清晰的实现方法:构造函数实现初始化,析构函数实现清理。这样就可以简单地使用shared_ptr管理对象。
(1) 为了避免隐式转换,智能指针不能使用赋值的方式初始化,使用括号初始化或者列表初始化是没有问题的。
(2) 另一种初始化的方法是使用make_shared<>,它是一种 更好且更安全 的方法:因为使用new时会创建一个对象,计算它的引用计数时会创建一个对象,而make_shared只会创建一个对象,并且不会出现控制模块失效的情况。
shared_ptr<string> p1 = make_shared<string>(10, ‘9‘); shared_ptr<string> p2 = make_shared<string>("hello"); shared_ptr<string> p3 = make_shared<string>();
(3) 先定义一个智能指针再进行赋值。但是不能使用赋值运算符(=),必须使用reset函数。
shared_ptr<string> pNico4; pNico4 = new string("nico"); // ERROR: no assignment for ordinary pointers pNico4.reset(new string("nico")); // OK
使用shared_ptr的主要原因是不想关注资源的释放。但是某些情况下shared_ptr会出现错误或者失效。
1、循环引用问题:如果两个对象使用shared_ptr指向彼此,当释放的时候,将不会自动释放资源,因为引用计数的计算有问题。
2、当共享对象的时候,指针的生命期要长于对象,因此对象不会被shared_ptr删除。指针就无法注意到对象是否释放。
如果一个资源将被多层传递和访问,那么参数类型该用 weak_ptr 还是 shared_ptr?
如何评价 C++11 的右值引用(Rvalue reference)特性?
unique_ptr相关
/* implement */
[c++] Why should I use Smart Pointers
原文:https://www.cnblogs.com/jesse123/p/12774971.html