首页 > 解决方案 > 如何将智能指针从函数传递给调用者?

问题描述

我试图掌握 C++ 中智能指针的概念。我有以下代码(使用 GoogleTest 的单元测试):

TEST(SHT35Sensor, ValidInstruction) {
    auto sht35 = SampleSHT35::create();
    sht35->add(22.4, 56.5);
    char writeBuffer[100] = {0};
    auto serial = std::make_unique<SampleSerial>("", writeBuffer, 0);
    auto sensor = std::make_unique<SHT35Sensor>(0x03, serial.get(), sht35, 0);
    auto actual = sensor->execute(Instruction(0, 0, Bytes("\x02", 1)));
    ASSERT_TRUE(actual);
}

我想隔离测试的前五行以便重用它们。我认为这样做就足够了(尤其是正确的):

std::shared_ptr<SHT35Sensor> prepare() {
    auto sht35 = SampleSHT35::create();
    sht35->add(22.4, 56.5);
    char writeBuffer[100] = {0};
    auto serial = std::make_unique<SampleSerial>("", writeBuffer, 0);
    return std::make_shared<SHT35Sensor>(0x03, serial.get(), sht35, 0);
}

TEST(SHT35Sensor, ValidInstruction) {
    auto sensor = prepare();
    auto actual = sensor->execute(Instruction(0, 0, Bytes("\x02", 1)));
    ASSERT_TRUE(actual);
}

本质上,我将代码移动到一个函数中,而不是unique_ptr,我使用shared_ptr它是为了能够在创建它的函数和调用者之间共享它。

但是,第二种变体在运行测试时会导致分段错误,这意味着我对智能指针的理解是不正确的。

我究竟做错了什么?

标签: c++smart-pointers

解决方案


在您的代码serial.get()中返回指针,但不会将其与 分离unique_ptr,因此当prepare ends- unique_ptr 删除SampleSerial实例并shared_ptr包含指向已释放内存的指针时。您可以使用serial.release()或直接使用shared_ptr.

上面的答案假设SHT35Sensor将处理SampleSerial实例的生命周期。但如果这不是真的,那么传递unique_ptr<SampleErial>SHT35Sensor

return std::make_shared<SHT35Sensor>(0x03, std::move(serial), sht35, 0);

SHT35Sensor应该接受std::unique_ptr<SampleErial>作为第二个参数 - 并使用构造函数初始化或再次将其传递给类成员std::move

我更喜欢第二种解决方案,因为它不会接受裸指针SHT35Sensor- 这很好。


推荐阅读