如何将智能指针从函数传递给调用者?

How do I pass a smart pointer from a function to the caller?

我正在尝试掌握 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 以便能够在创建它的函数和调用者之间共享它。

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

我做错了什么?

在您的代码中 serial.get() returns 指针,但不会将其与 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> 作为第二个参数 - 并使用构造函数初始化或再次将其传递给 class 成员 std::move.

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