CppCoreGuidelines F.26 用 unique_ptr 传递指针所有权
18 June 2022
F.26: Use a unique_ptr<T>
to transfer ownership where a pointer is needed
理由
unique_ptr
是安全传递指针的最轻量的方法。
如果返回值是shared_ptr
请查看CppCoreGuidelines C.50如果初始化阶段需要一些虚行为,可以用工厂函数
例子
// -*- compile-command: "g++ -std=c++20 code.cpp && ./a"; -*- #include <iostream> #include <sstream> #include <gsl/gsl> using namespace std; using namespace gsl; enum shape_type { kCircle = 0, kTriangle = 1}; class Shape { public: Shape() {cout << "Shape\n";} virtual ~Shape() = default; }; class Circle: public Shape { public: Circle(istream& is){cout<<"Circle\n";}; ~Circle(){cout<< "~Circle\n";}; }; class Triangle: public Shape { public: Triangle(istream& is){cout<<"Triangle\n";}; ~Triangle(){cout<< "~Triangle\n";}; }; const shape_type read_header(istream& is) { int shape; is >> shape; return shape_type(shape); } // assemble shape from input stream unique_ptr<Shape> get_shape(istream& is) { auto kind = read_header(is); switch (kind) { case kCircle: return make_unique<Circle>(is); case kTriangle: return make_unique<Triangle>(is); default: return nullptr; } } int main() { stringstream ss1{"0 circle"}; get_shape(ss1); // 自动销毁 Circle stringstream ss2{"1 triangle"}; get_shape(ss2); // 自动销毁 Triangle return 0; }
Shape Circle ~Circle Shape Triangle ~Triangle
不用unique_ptr
的话,就没法自动销毁两个对象,需要手动销毁:
// -*- compile-command: "g++ -std=c++20 code.cpp && ./a"; -*- #include <iostream> #include <sstream> #include <gsl/gsl> using namespace std; using namespace gsl; enum shape_type { kCircle = 0, kTriangle = 1}; class Shape { public: Shape() {cout << "Shape\n";} virtual ~Shape() = default; }; class Circle: public Shape { public: Circle(istream& is){cout<<"Circle\n";}; ~Circle(){cout<< "~Circle\n";}; }; class Triangle: public Shape { public: Triangle(istream& is){cout<<"Triangle\n";}; ~Triangle(){cout<< "~Triangle\n";}; }; const shape_type read_header(istream& is) { int shape; is >> shape; return shape_type(shape); } // assemble shape from input stream Shape* get_shape(istream& is) { auto kind = read_header(is); switch (kind) { case kCircle: return new Circle(is); case kTriangle: return new Triangle(is); default: return nullptr; } } int main() { stringstream ss1{"0 circle"}; get_shape(ss1); // 没有自动销毁 Circle stringstream ss2{"1 triangle"}; auto shape = get_shape(ss2); delete shape; // 销毁 Triangle return 0; }
Shape Circle Shape Triangle ~Triangle
注意
如果需要运用类层级上基类的接口函数的话,你需要传递一个指针而不是对象。
强化
- (简单)如果函数返回一个局部的原始指针的话,需要进行警告。建议使用
unique_ptr
或shared_ptr
。