为什么在这个例子中没有调用一些析构函数

Why are some destructors not called in this example

试图了解这里发生了什么以及为什么一些析构函数没有被调用。当我 运行 程序(下面的示例)时,我期望输出来自所有 SPI/I2CGPIO 外围设备 classes 的析构函数,但是他们没有接到电话。相反,我只看到从 SystemProvider class.

的析构函数调用的输出

注:还是C++的初学者

Header:

#include <string>
#include <memory>

class Provider;

// =========================================================================================
//                           TOP LEVEL PERIPHERAL CLASS
// =========================================================================================

class Peripheral {
public:

    explicit Peripheral(std::shared_ptr<Provider> provider);

    virtual ~Peripheral();

    [[nodiscard]] const std::shared_ptr<Provider> &getProvider() const;

private:
    std::shared_ptr<Provider> m_Provider;
};

// =========================================================================================
//                           BASE PERIPHERAL CLASSES
// =========================================================================================

class I2CPeripheral : public Peripheral {
public:
    explicit I2CPeripheral(std::shared_ptr<Provider> provider);

    ~I2CPeripheral() override;

    virtual void write(int address, char* buf, int size) = 0;
};

class GpioPeripheral : public Peripheral {
public:
    explicit GpioPeripheral(std::shared_ptr<Provider> provider);

    ~GpioPeripheral() override;

    virtual void init(int pin, int mode) = 0;

    virtual void write(int pin, int value) = 0;
};

class SpiPeripheral : public Peripheral {
public:
    explicit SpiPeripheral(std::shared_ptr<Provider> provider);

    ~SpiPeripheral() override;

    virtual void write(char *buffer, int size) = 0;
};

// =========================================================================================
//               CONCRETE (PROVIDER SPECIFIC) PERIPHERAL CLASSES
// =========================================================================================

class SystemI2CPeripheral : public I2CPeripheral {
public:
    explicit SystemI2CPeripheral(std::shared_ptr<Provider> provider);

    ~SystemI2CPeripheral() override;

    void write(int address, char *buf, int size) override;
};

class SystemGpioPeripheral : public GpioPeripheral {
public:
    explicit SystemGpioPeripheral(std::shared_ptr<Provider> provider);

    ~SystemGpioPeripheral() override;

    void init(int pin, int mode) override;

    void write(int pin, int value) override;
};

class SystemSpiPeripheral : public SpiPeripheral {
public:
    explicit SystemSpiPeripheral(std::shared_ptr<Provider> provider);

    ~SystemSpiPeripheral() override;

    void write(char *buffer, int size) override;
};

class PigpioGpioPeripheral : public GpioPeripheral {
public:
    explicit PigpioGpioPeripheral(std::shared_ptr<Provider> provider);

    ~PigpioGpioPeripheral() override;

    void init(int pin, int mode) override;

    void write(int pin, int value) override;
};

class PigpioI2CPeripheral : public I2CPeripheral {
public:
    explicit PigpioI2CPeripheral(std::shared_ptr<Provider> provider);

    ~PigpioI2CPeripheral() override;

    void write(int address, char *buf, int size) override;
};

class PigpioSpiPeripheral : public SpiPeripheral {
public:
    explicit PigpioSpiPeripheral(std::shared_ptr<Provider> provider);

    ~PigpioSpiPeripheral() override;

    void write(char *buffer, int size) override;
};

// =========================================================================================
//                           BASE PROVIDER CLASS
// =========================================================================================

class Provider {
public:
    Provider() = default;

    explicit Provider(std::string name);

    virtual ~Provider();

    std::string getName();

    virtual std::shared_ptr<GpioPeripheral> getGpioPeripheral();

    virtual std::shared_ptr<I2CPeripheral> getI2CPeripheral();

    virtual std::shared_ptr<SpiPeripheral> getSpiPeripheral();
protected:
    std::shared_ptr<GpioPeripheral> gpioPeripheral;

    std::shared_ptr<SpiPeripheral> spiPeripheral;

    std::shared_ptr<I2CPeripheral> i2cPeripheral;

    virtual std::shared_ptr<GpioPeripheral> createGpioPeripheral() = 0;

    virtual std::shared_ptr<I2CPeripheral> createI2CPeripheral() = 0;

    virtual std::shared_ptr<SpiPeripheral> createSpiPeripheral() = 0;

private:
    std::string name;
};

// =========================================================================================
//                           CONCRETE PROVIDER CLASSES
// =========================================================================================

class SystemProvider : public Provider, public std::enable_shared_from_this<SystemProvider> {
public:
    SystemProvider();

    ~SystemProvider() override;

    std::shared_ptr<SystemProvider> getPointer() {
        return this->shared_from_this();
    }
protected:
    std::shared_ptr<GpioPeripheral> createGpioPeripheral() override;

    std::shared_ptr<I2CPeripheral> createI2CPeripheral() override;

    std::shared_ptr<SpiPeripheral> createSpiPeripheral() override;
};

class PigpioProvider : public Provider, public std::enable_shared_from_this<PigpioProvider> {
public:

    PigpioProvider();

    ~PigpioProvider() override;

    std::shared_ptr<PigpioProvider> getPointer() {
        return this->shared_from_this();
    }
protected:
    std::shared_ptr<GpioPeripheral> createGpioPeripheral() override;

    std::shared_ptr<I2CPeripheral> createI2CPeripheral() override;

    std::shared_ptr<SpiPeripheral> createSpiPeripheral() override;
};

来源:

#include "Peripherals.h"

#include "Common.h"

Peripheral::Peripheral(std::shared_ptr<Provider> provider) : m_Provider(provider) {
    debug("Peripheral: constructor");
}

Peripheral::~Peripheral() {
    debug("Peripheral: destructor");
}

const std::shared_ptr<Provider> &Peripheral::getProvider() const {
    return m_Provider;
}

I2CPeripheral::I2CPeripheral(std::shared_ptr<Provider> provider) : Peripheral(provider) {
    debug("\tI2CPeripheral: constructor");
}

I2CPeripheral::~I2CPeripheral() {
    debug("I2CPeripheral: destructor");
}

GpioPeripheral::GpioPeripheral(std::shared_ptr<Provider> provider) : Peripheral(provider) {
    debug("\tGpioPeripheral: constructor");
}

GpioPeripheral::~GpioPeripheral() {
    debug("GpioPeripheral: destructor");
}

SpiPeripheral::SpiPeripheral(std::shared_ptr<Provider> provider) : Peripheral(provider) {
    debug("\tSpiPeripheral: constructor");
}

SpiPeripheral::~SpiPeripheral() {
    debug("SpiPeripheral: destructor");
}

SystemI2CPeripheral::SystemI2CPeripheral(std::shared_ptr<Provider> provider) : I2CPeripheral(provider) {
    debug("\t\tSystemI2CPeripheral: constructor");
}

SystemI2CPeripheral::~SystemI2CPeripheral() {
    debug("SystemI2CPeripheral: destructor");
}

void SystemI2CPeripheral::write(int address, char *buf, int size) {

}

SystemGpioPeripheral::SystemGpioPeripheral(std::shared_ptr<Provider> provider) : GpioPeripheral(provider) {
    debug("\t\tSystemGpioPeripheral: constructor");
}

SystemGpioPeripheral::~SystemGpioPeripheral() {
    debug("SystemGpioPeripheral: destructor");
}

void SystemGpioPeripheral::init(int pin, int mode) {

}

void SystemGpioPeripheral::write(int pin, int value) {

}

SystemSpiPeripheral::SystemSpiPeripheral(std::shared_ptr<Provider> provider) : SpiPeripheral(provider) {
    debug("\t\tSystemSpiPeripheral: constructor");
}

SystemSpiPeripheral::~SystemSpiPeripheral() {
    debug("SystemSpiPeripheral: destructorr");
}

void SystemSpiPeripheral::write(char *buffer, int size) {
    debug(std::string(__func__) + std::string(": Writing to SPI peripheral with ") + std::to_string(size) + std::string(" bytes"));
}

PigpioGpioPeripheral::PigpioGpioPeripheral(std::shared_ptr<Provider> provider) : GpioPeripheral(provider) {
    debug("\t\tPigpioGpioPeripheral: constructor");
}

PigpioGpioPeripheral::~PigpioGpioPeripheral() {
    debug("PigpioGpioPeripheral: destructor");
}

void PigpioGpioPeripheral::init(int pin, int mode) {

}

void PigpioGpioPeripheral::write(int pin, int value) {

}

PigpioI2CPeripheral::PigpioI2CPeripheral(std::shared_ptr<Provider> provider) : I2CPeripheral(provider) {
    debug("\t\tPigpioI2CPeripheral: constructor");
}

PigpioI2CPeripheral::~PigpioI2CPeripheral() {
    debug("PigpioI2CPeripheral: destructor");
}

void PigpioI2CPeripheral::write(int address, char *buf, int size) {

}

PigpioSpiPeripheral::PigpioSpiPeripheral(std::shared_ptr<Provider> provider) : SpiPeripheral(provider) {
    debug("\t\tPigpioSpiPeripheral: constructor");
}

PigpioSpiPeripheral::~PigpioSpiPeripheral() {
    debug("PigpioSpiPeripheral: destructor");
}

void PigpioSpiPeripheral::write(char *buffer, int size) {
    debug(std::string(__func__) + std::string(": Writing to SPI peripheral with ") + std::to_string(size) + std::string(" bytes"));
}

Provider::Provider(std::string name) : name(std::move(name)) {
    debug("Provider: constuctor");
}

Provider::~Provider() {
    debug("\tProvider: destructor");
    gpioPeripheral = nullptr;
    spiPeripheral = nullptr;
    i2cPeripheral = nullptr;
}

std::string Provider::getName() {
    return name;
}

std::shared_ptr<GpioPeripheral> Provider::getGpioPeripheral() {
    if (gpioPeripheral == nullptr) {
        debug(std::string("Creating a new instance of gpio peripheral for provider: ") + getName());
        gpioPeripheral = createGpioPeripheral();
    } else {
        debug("Using existing instance of gpioPeripheral");
    }
    return gpioPeripheral;
}

std::shared_ptr<I2CPeripheral> Provider::getI2CPeripheral() {
    if (i2cPeripheral == nullptr) {
        debug(std::string("Creating a new instance of i2c peripheral for provider: ") + getName());
        i2cPeripheral = createI2CPeripheral();
    }
    return i2cPeripheral;
}

std::shared_ptr<SpiPeripheral> Provider::getSpiPeripheral() {
    if (spiPeripheral == nullptr) {
        debug(std::string("Creating a new instance of spi peripheral for provider: ") + getName());
        spiPeripheral = createSpiPeripheral();
    }
    return spiPeripheral;
}

SystemProvider::SystemProvider() : Provider("system") {
    debug("\tSystemProvider: constructor");
}

SystemProvider::~SystemProvider() {
    debug("SystemProvider: destructor");
}

std::shared_ptr<GpioPeripheral> SystemProvider::createGpioPeripheral() {
    return std::make_shared<SystemGpioPeripheral>(getPointer());
}

std::shared_ptr<I2CPeripheral> SystemProvider::createI2CPeripheral() {
    return std::make_shared<SystemI2CPeripheral>(getPointer());
}

std::shared_ptr<SpiPeripheral> SystemProvider::createSpiPeripheral() {
    return std::make_shared<SystemSpiPeripheral>(getPointer());
}

PigpioProvider::PigpioProvider() : Provider("pigpio") {
    debug("\tPigpioProvider: constructor");
}

PigpioProvider::~PigpioProvider() {
    debug("PigpioProvider: destructor");
}

std::shared_ptr<GpioPeripheral> PigpioProvider::createGpioPeripheral() {
    return std::make_shared<PigpioGpioPeripheral>(getPointer());
}

std::shared_ptr<I2CPeripheral> PigpioProvider::createI2CPeripheral() {
    return std::make_shared<PigpioI2CPeripheral>(getPointer());
}

std::shared_ptr<SpiPeripheral> PigpioProvider::createSpiPeripheral() {
    return std::make_shared<PigpioSpiPeripheral>(getPointer());
}

主要可执行文件:

void debug(const std::string& msg) {
    std::cout << "[debug] " << msg << std::endl;
}

int main() {
    //Two providers available for SPI/I2C and GPIO peripherals
    debug("==============================================================");
    debug("Peripheral Providers (Instantiate both)");
    debug("==============================================================");
    std::shared_ptr<PigpioProvider> pigpioProvider = std::make_shared<PigpioProvider>();
    std::shared_ptr<SystemProvider> systemProvider = std::make_shared<SystemProvider>();

    debug("==============================================================");
    debug("Retrieve peripherals from the selected provider");
    debug("==============================================================");

    //Choose a default peripheral provider (pigpioProvider or systemProvider)
    std::shared_ptr<Provider> defaultProvider = pigpioProvider;
    //std::shared_ptr<Provider> defaultProvider = systemProvider;

    //Retrieve the peripheral interfaces
    std::shared_ptr<GpioPeripheral> gpio = defaultProvider->getGpioPeripheral();
    std::shared_ptr<I2CPeripheral> i2c = defaultProvider->getI2CPeripheral();
    std::shared_ptr<SpiPeripheral> spi = defaultProvider->getSpiPeripheral();

    //Test
    gpio->write(10, 1);
    i2c->write(0x10, nullptr, 0);
    spi->write(nullptr, 0);

    debug("==============================================================");
    debug("Exiting program...");
    debug("==============================================================");

    return 0;
}

输出:

[debug] ==============================================================
[debug] Peripheral Providers (Instantiate both)
[debug] ==============================================================
[debug] Provider: constuctor
[debug]     PigpioProvider: constructor
[debug] Provider: constuctor
[debug]     SystemProvider: constructor
[debug] ==============================================================
[debug] Retrieve peripherals from the selected provider
[debug] ==============================================================
[debug] Creating a new instance of gpio peripheral for provider: pigpio
[debug] Peripheral: constructor
[debug]     GpioPeripheral: constructor
[debug]         PigpioGpioPeripheral: constructor
[debug] Creating a new instance of i2c peripheral for provider: pigpio
[debug] Peripheral: constructor
[debug]     I2CPeripheral: constructor
[debug]         PigpioI2CPeripheral: constructor
[debug] Creating a new instance of spi peripheral for provider: pigpio
[debug] Peripheral: constructor
[debug]     SpiPeripheral: constructor
[debug]         PigpioSpiPeripheral: constructor
[debug] write: Writing to SPI peripheral with 0 bytes
[debug] ==============================================================
[debug] Exiting program...
[debug] ==============================================================
[debug] SystemProvider: destructor
[debug]     Provider: destructor

注意最后的输出:

[debug] SystemProvider: destructor
[debug]     Provider: destructor

但我希望输出看起来像这样:

[debug] PigpioProvider: destructor
[debug]     Provider: destructor
[debug] PigpioGpioPeripheral: destructor
[debug]     GpioPeripheral: destructor
[debug]         Peripheral: destructor
[debug] PigpioI2CPeripheral: destructor
[debug]     I2cPeripheral: destructor
[debug]         Peripheral: destructor
[debug] PigpioSpiPeripheral: destructor
[debug]     SpiPeripheral: destructor
[debug]         Peripheral: destructor

提供者谁拥有外围设备还是外围设备谁拥有提供商?

您在两个方向上都使用了 std::shared_ptr,因此创建了所有权循环。

你必须在你的设计中决定哪个关系是前向,(归shared_ptr所有)哪个是后向(由weak_ptr引用,暂时分配给shared_ptr)

您的提供商 class 维护 shared_ptrs 外围设备。例如:

class Provider
{
public:
  Provider() = default;
  // ...
protected:
  std::shared_ptr<GpioPeripheral> gpioPeripheral;
  std::shared_ptr<SpiPeripheral> spiPeripheral;
  std::shared_ptr<I2CPeripheral> i2cPeripheral;
};

但是,由于继承自外围设备父级 class:

,您的外围设备还维护默认提供程序的 shared_ptr
class Peripheral
{
public:
  explicit Peripheral(std::shared_ptr<Provider> provider);
  // ...
private:
  std::shared_ptr<Provider> m_Provider;
};

这会导致循环依赖链,导致 shared_ptr 永远不会 被清理。

我建议将 m_Provider 改为 std::weak_ptr 而不是 std::shared_ptr。从您分享的示例中,我不相信外围设备 拥有 提供商。