18 June 2022

C++ 核心指南目录

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_ptrshared_ptr