Skip to content

c++中智能指针的应用

涉及到的头文件包括<memory>

独占指针 std::unique_ptr

独占指针是一种带有所有权的智能指针

在私有成员中使用:

cpp
#include <memory>

struct Info {};

class Test {
public:
    Test() : info_(std::make_unique<Info>()) {}
    ~Test() = default;

private:
    std::unique_ptr<Info> info_ = nullptr;
};
#include <memory>

struct Info {};

class Test {
public:
    Test() : info_(std::make_unique<Info>()) {}
    ~Test() = default;

private:
    std::unique_ptr<Info> info_ = nullptr;
};

在传递消息时使用:

cpp
#include <memory>

struct Info {
    // 超~大的结构体
};

class Container {
public:
    void Set(std::unique_ptr<Info> info) {
        // do something.
    }
};

class Test {
public:
    Test() : container_(std::make_unique<Container>()) {}
    void Make() {
        std::unique_ptr<Info> info = std::make_unique<Info>();
        container_->Set(std::move(info));
    }

private:
    std::unique_ptr<Container> container_;
};
#include <memory>

struct Info {
    // 超~大的结构体
};

class Container {
public:
    void Set(std::unique_ptr<Info> info) {
        // do something.
    }
};

class Test {
public:
    Test() : container_(std::make_unique<Container>()) {}
    void Make() {
        std::unique_ptr<Info> info = std::make_unique<Info>();
        container_->Set(std::move(info));
    }

private:
    std::unique_ptr<Container> container_;
};

使用独占指针存储数组

cpp
#include <cstdlib>
#include <cstring>
#include <memory>

void *originData = std::malloc(1024);

std::unique_ptr<uint8_t[]> Make() {
    std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(1024);
    memcpy(data.get(), originData, 1024);
    return data;
}

class ImageContainer {
public:
    void MakeImage() {
        data_ = Make();
    }

private:
    std::unique_ptr<uint8_t[]> data_ = nullptr;
};
#include <cstdlib>
#include <cstring>
#include <memory>

void *originData = std::malloc(1024);

std::unique_ptr<uint8_t[]> Make() {
    std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(1024);
    memcpy(data.get(), originData, 1024);
    return data;
}

class ImageContainer {
public:
    void MakeImage() {
        data_ = Make();
    }

private:
    std::unique_ptr<uint8_t[]> data_ = nullptr;
};

巧用deleter

cpp
#include <fstream>
#include <memory>

void Write(const char *fileData, size_t size, const char* fileName) {
    auto deleter = [] (std::ofstream *file) {
        if (!file->is_open()) {
            file->flush();
            file->close();
        }
    };
    std::unique_ptr<std::ofstream, decltype(deleter)> file(new std::ofstream(), deleter);
    if (fileData == nullptr || fileName == nullptr) {
        return;
    }
    if (size <= 0) {
        return;
    }
    file->open(fileName, std::ios::out);
    // do something.
    if (false) {
        return;
    }
    file->write(fileData, size);
}
#include <fstream>
#include <memory>

void Write(const char *fileData, size_t size, const char* fileName) {
    auto deleter = [] (std::ofstream *file) {
        if (!file->is_open()) {
            file->flush();
            file->close();
        }
    };
    std::unique_ptr<std::ofstream, decltype(deleter)> file(new std::ofstream(), deleter);
    if (fileData == nullptr || fileName == nullptr) {
        return;
    }
    if (size <= 0) {
        return;
    }
    file->open(fileName, std::ios::out);
    // do something.
    if (false) {
        return;
    }
    file->write(fileData, size);
}

共享指针 std::shared_ptr

cpp
#include <memory>

struct Attribute {};

class Render {
public:
    explicit Render(std::shared_ptr<const Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<const Attribute> attribute_ = nullptr;
};

class Factory {
public:
    explicit Factory(std::shared_ptr<Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<Attribute> attribute_ = nullptr;
};

class Container {
public:
    explicit Container(std::shared_ptr<Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<Attribute> attribute_ = nullptr;
};

std::shared_ptr<Attribute> MakeAttribute()
{
    // do something.
    return std::make_shared<Attribute>();
}

int main()
{
    std::shared_ptr<Attribute> attribute = MakeAttribute();

    std::unique_ptr<Render> render = std::make_unique<Render>(attribute);
    std::unique_ptr<Factory> factory = std::make_unique<Factory>(attribute);
    std::unique_ptr<Container> container = std::make_unique<Container>(attribute);

    return 0;
}
#include <memory>

struct Attribute {};

class Render {
public:
    explicit Render(std::shared_ptr<const Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<const Attribute> attribute_ = nullptr;
};

class Factory {
public:
    explicit Factory(std::shared_ptr<Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<Attribute> attribute_ = nullptr;
};

class Container {
public:
    explicit Container(std::shared_ptr<Attribute> attribute) : attribute_(attribute) {}

private:
    std::shared_ptr<Attribute> attribute_ = nullptr;
};

std::shared_ptr<Attribute> MakeAttribute()
{
    // do something.
    return std::make_shared<Attribute>();
}

int main()
{
    std::shared_ptr<Attribute> attribute = MakeAttribute();

    std::unique_ptr<Render> render = std::make_unique<Render>(attribute);
    std::unique_ptr<Factory> factory = std::make_unique<Factory>(attribute);
    std::unique_ptr<Container> container = std::make_unique<Container>(attribute);

    return 0;
}

弱引用计数指针 std::weak_ptr

cpp
#include <memory>

class Container;
class Manager {
public:
    Manager(std::weak_ptr<Container> container) : container_(container) {}
    ~Manager() { std::cout << "~Manager" << std::endl; }

private:
    std::weak_ptr<Container> container_;
};

class Container {
public:
    ~Container() { std::cout << "~Container" << std::endl; }

    void SetManager(std::shared_ptr<Manager> manager)
    {
        manager_ = manager;
    }

private:
    std::shared_ptr<Manager> manager_ = nullptr;
};

int main() {
    auto container = std::make_shared<Container>();
    auto manager = std::make_shared<Manager>(container);
    container->SetManager(manager);

    return 0;
}
#include <memory>

class Container;
class Manager {
public:
    Manager(std::weak_ptr<Container> container) : container_(container) {}
    ~Manager() { std::cout << "~Manager" << std::endl; }

private:
    std::weak_ptr<Container> container_;
};

class Container {
public:
    ~Container() { std::cout << "~Container" << std::endl; }

    void SetManager(std::shared_ptr<Manager> manager)
    {
        manager_ = manager;
    }

private:
    std::shared_ptr<Manager> manager_ = nullptr;
};

int main() {
    auto container = std::make_shared<Container>();
    auto manager = std::make_shared<Manager>(container);
    container->SetManager(manager);

    return 0;
}