访问另一个 class 中指向 class 的智能指针的属性时出现分段错误

segmentation fault when acessing attribute of an smart pointer to class, inside another class

我试着做这个:

#include <iostream>
#include <memory>

class B
{
    public:
    std::string var;
    
    B()
    {
        var = "original";
    }

    void print()
    {  
        std::cout << "composition " << std::endl;
    }
};

class A
{
    public:
    int a_attribute = 10;
    std::unique_ptr<B> b;

};

int main()
{
    A a;
    a.b->print();
}

这似乎工作正常,除非我尝试访问 B 的属性,例如:

std::string test = a.b->var;

这会导致 segmentation fault 错误

为什么我没有收到 a.b->print(); 的错误,但收到 a.b->var; 的段错误?

你的问题在这里,在A你有

std::unique_ptr<B> b;

这将创建一个指向 B 对象的智能指针。 但是它没有指向B对象。在使用它之前,您必须创建一个 B 对象并设置 'b' 指向它。

我不确切知道您想如何以及何时创建 B,但您可以这样做

A a;
a.b = std::make_unique<B>();
a.b->print();

这将使用默认构造函数创建一个新的 B 并使 'a.b' 指向它。这是

更有效的简写
A a;
B *b1 = new B;
a.b.reset(b1);
a.b->print();

它明确地创建了一个 B 然后设置 a.b 指向它。

请注意,您不必释放 B 对象。这就是智能指针的意义所在,他们会为您完成。

您问过为什么有些组合有效而有些无效。

您有未定义的行为。这可以做任何事情,包括最糟糕的,看起来有效。然后在圣诞节前夜的午夜,你最大的客户向你的系统提交了一个巨大的订单,然后它崩溃了。每个专业开发人员都遇到过这种情况。避免方法:提高编译器警告级别,永远不要忽略警告。使用类似 valgrind 或其他商业检查工具的工具。

对我来说,您发布的原始代码有效。为什么,因为调用的方法实际上不需要 B 对象中的任何数据。但是如果我改成这个

void print()
{
    std::cout << "composition " << std::endl;
    std::cout << var << std::endl;
}

它失败了,因为现在我们正在引用 B 对象中的数据,但是没有。

请注意,在不同的编译器上,您的原始代码将无法运行