我有一个对象(我们称之为 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 之外做它。
您应该将
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));
//
}