【问题标题】:Problem with reference initialization in constructor构造函数中的引用初始化问题
【发布时间】:2018-09-07 08:55:13
【问题描述】:

类伪定义:

基础虚拟类 A:

class A {
public:
    virtual ~A();
    virtual void doSomething() const = 0;
};

从 A 继承的 B 类:

class B : public A {
public:
    void doSomething() {} const;
}

基础虚拟类 C:

class C {
public:
    virtual ~C();
    virtual void doSomething() const = 0;
};

从 C 继承的 D 类:

class D : public C {
public:
    D(const &A _a = *A_Ptr(new B)) : a(_a) {}
    void doSomething() {} const;
private:
    const &A a;
}

A_Ptr 是 A 类共享指针的 typedef。

我的问题是声明另一个类。

我们称之为 X 类:

class X {
public:
    X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) : a(_a), c(_c) {}
private:
    const &A a;
    const &C c;
}

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a)) - 这部分初始化不起作用。什么工作是

X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D)

但如果我这样做,我会创建两个 A 类类型的共享指针,这不是我想要的。另一方面,X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(a))X(const &A _a = *A_Ptr(new B), const &C _c = *C_Ptr(new D(_a)) 之类的任何东西都不起作用。有没有已知的方法来解决这个问题?

提前致谢:)

【问题讨论】:

  • 顺便说一句,如果使用默认参数,const &A _a = *A_Ptr(new B) 是内存泄漏!
  • 为什么X 的成员是引用,而实际上它们不应该引用某些东西?我的意思是A_Ptr(new B) 不是别人拥有的东西,X 只是想引用,但似乎X 应该拥有它
  • @Some 程序员老兄:正如我所说,它是共享指针,所以一旦不再使用,内存就会被释放。 @ user463035818:这是项目问题,我无法更改继承级别。有必要这样做。当我使用所述声明创建两个 A 类类型的对象时,我没有遇到问题。成员应该是对这些对象的常量引用,如果没有引用现有对象的参数,这些对象将被动态创建。
  • @Advent 而shared_ptr 将在构造函数完成后立即停止使用,因此您从那时起就有一个悬空引用...
  • 好吧,不得不承认我刚刚意识到我也没有完全理解发生了什么;)。不过,我仍然认为您在这里的示例可能不那么冗长,并且仍然会产生相同的错误

标签: c++ reference initialization smart-pointers


【解决方案1】:

如果我理解正确,您需要一个使用外部资源或管理自己的资源的类。如果是这种情况,您必须允许班级两者都做。我相信它可以像这样工作:

class D : public C {
public:
    D() : myA(new B), a(*myA) {}
    D(const &A _a) : a(_a) {}
    void doSomething() {} const;
private:
    std::unique_ptr<A> myA;
    const &A a;
}

这样,D 可以在没有参数的情况下创建,并且将正确管理绑定到a 的对象的生命周期,或者可以使用外部提供的A 创建它,并且不会自己创建任何东西。

可以对X进行类似的更改:

class X {
public:
    X() : myA(new B), a(*myA), myC(new D(a)), c(*myC) {}
    X(const &A _a) : a(_a), myC(new D(a)), c(*myC) {}
    X(const &A _a, const &C _c) : a(_a), c(_c) {}
private:
    std::unique_ptr<A> myA;
    const &A a;
    std::unique_ptr<C> myC;
    const &C c;
}

请注意,您的原始代码有悬挂引用,因为当构造函数运行完成时,作为默认参数创建的智能指针超出范围。这就是为什么它们必须存储在类中的某个位置,就像上面的解决方案一样。

【讨论】:

  • 我已经使用valgrind检查是否有任何泄漏,没有。
  • @Advent 不,没有泄漏,但有悬空引用。
猜你喜欢
  • 2023-02-07
  • 2016-06-07
  • 1970-01-01
  • 1970-01-01
  • 2017-10-15
  • 1970-01-01
  • 1970-01-01
  • 2016-05-01
  • 1970-01-01
相关资源
最近更新 更多