c++ 将所有权传递给复合类

问题描述 投票:0回答:1

我有一个对象(我们称之为 A),我想存储另一个对象(假设它的类型为 B,称为 m),该对象将从创建 A 的函数传递。B 的创建是由另一个对象创建的我无法控制的功能。

class A
{
    public:
    A(B& m)
    {
        this->m = m
    }

    private:
    B& m;
};

//

void SomeLongLivedClass::someFunction()
{
    B m = createB();
    A a = new A{ m }

    // m goes out of scope
}

当 someFunction() 的作用域结束时,m 被销毁,A 中的引用变为悬空。我只能通过createB()获得正确的B,它是我无权访问的dll的一部分。如何使 m 成为左值并将所有权传递给 A?

我选择在 A 之外创建 B 以减少 A 中的混乱,但也许这是一个根本错误的方法?我读过一些关于组合与聚合的内容 - 通过将对象推入这样的类中进行组合是错误的吗?

我考虑过将 m 作为 std::unique_ptr 传递,但我无法思考 m 是否仍会超出范围,然后让指针悬空。

不用说,这只是伪代码,真实情况要复杂得多。 B 的创建比这要复杂一些,这就是为什么我想在 A 之外做它。

c++ pointers reference composition ownership
1个回答
0
投票

您应该将

B
存储在
A
中,而不是
B&
。如果存储引用,则在超出范围后访问引用的对象会出现未定义的行为。

而是将

m
复制或移动到
A
。一个简单的版本是在
B
的构造函数中按值获取
A

class A {
public:
    A(B m) : m(std::move(m)) {}    // take by value, then move

private:
    B m;
};

另一种选择是提供以下一个或两个构造函数:

class A {
public:
    A(const B& m) : m(m) {}        // copy m
    A(B&& m) : m(std::move(m)) {}  // move m
    
private:
    B m;
};

然后在调用代码中,如果您有左值,请使用

std::move
:

将其转换为右值引用
void SomeLongLivedClass::someFunction() {
    B m = createB();
    // 
    A* a = new A(std::move(m));
    //
}
© www.soinside.com 2019 - 2024. All rights reserved.