C++: auto_ptr +前向声明?

发布于 2024-08-15 08:21:46 字数 867 浏览 9 评论 0原文

我有一个这样的类:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    Inner* m_inner;
};

在 .cpp 中,构造函数使用 new 创建一个 Inner 实例,析构函数删除它。这工作得很好。
现在我想更改此代码以使用 auto_ptr 所以我写道:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    std::auto_ptr<Inner> m_inner;
};

现在,构造函数初始化了 auto_ptr 并且析构函数不执行任何操作。

但这不起作用。当我实例化这个类时,问题似乎出现了。我收到这个警告:

警告 C4150:删除指向 不完整类型“内部”;不 析构函数调用

嗯,这显然是非常糟糕的,我明白为什么会发生这种情况,编译器在实例化 auto_ptr 模板时不知道 Inner 的 d'tor 。 code>

所以我的问题:有没有办法像我在仅使用普通指针的版本中那样使用带有前向声明的 auto_ptr
必须#include我声明指向的每个类是一个巨大的麻烦,有时甚至是不可能的。这个问题通常是如何处理的?

I have a class like this:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    Inner* m_inner;
};

in the .cpp, the constructor creates an instance of Inner with new and the destructor deletes it. This is working pretty well.
Now I want to change this code to use auto_ptr so I write:

class Inner;

class Cont
{
public:
    Cont();
    virtual ~Cont();
private:
    std::auto_ptr<Inner> m_inner;
};

Now, the constructor initialized the auto_ptr and the destructor does nothing.

But it doesn't work. the problem seem to arise when I'm instantiating this class. I get this warning:

warning C4150: deletion of pointer to
incomplete type 'Inner'; no
destructor called

Well, this is obviously very bad and I understand why it happens, The compiler doesn't know about the d'tor of Inner when instantiating the template of auto_ptr<Inner>

So my question: Is there a way to use auto_ptr with a forward declaration like I did in the version that uses just plain pointers?
Having to #include every class I declare a pointer to is a huge hassle and at times, just impossible. How is this problem usually handled?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

千纸鹤 2024-08-22 08:21:46

您需要将定义 class Inner 的标头包含到 Cont::~Cont() 实现所在的文件中。这样,您仍然可以在定义 class Cont 的标头中进行前向声明,并且编译器会看到 class Inner 定义并可以调用析构函数。

//Cont.h
class Inner; // is defined in Inner.h
class Cont 
{ 
    virtual ~Cont(); 
    std::auto_ptr<Inner> m_inner;
};

// Cont.cpp
#include <Cont.h>
#include <Inner.h>

Cont::~Cont()
{
}

You need to include the header defining class Inner into the file where Cont::~Cont() implementation is located. This way you still have a forward declaration in teh header defining class Cont and the compiler sees class Inner definition and can call the destructor.

//Cont.h
class Inner; // is defined in Inner.h
class Cont 
{ 
    virtual ~Cont(); 
    std::auto_ptr<Inner> m_inner;
};

// Cont.cpp
#include <Cont.h>
#include <Inner.h>

Cont::~Cont()
{
}
梦过后 2024-08-22 08:21:46

事实证明,只有当我使 c'tor 内联时才会出现问题。如果我将 c'tor 放入 cpp 中,则在 Inner 减速后一切正常。

Turns out the problem occurs only when I make the c'tor inline. If I put the c'tor in the cpp, after the decleration of Inner everything's ok.

陌伤ぢ 2024-08-22 08:21:46

您可以考虑使用 boost::shared_ptr() 来代替。它除了性能之外没有任何实际缺点,并且对前向声明更加友好:

boost::shared_ptrptr;

没问题,上面没有额外的声明。

shared_ptr 比 auto_ptr 做更多的事情,例如引用计数,但如果您不需要它,它应该不会造成损害。

You may consider boost::shared_ptr() instead. It has no practical disadvantages instead of performance, and is much more friendly to forward declarations:

boost::shared_ptr<class NeverHeardNameBefore> ptr;

is okay, without extra declarations above.

shared_ptr does more than auto_ptr, such as reference counting, but it should not harm if you don't need it.

寂寞笑我太脆弱 2024-08-22 08:21:46

这似乎很荒谬,但我通过将 #include 添加到 Cont.h 文件解决了同样的问题。

It seems to be ridiculous but I solved the same issue by adding #include <memory> to the Cont.h file.

べ繥欢鉨o。 2024-08-22 08:21:46

如果您在 cont.cpp 文件中实现析构函数并且包含inner.h,则头中的前向声明是可以的,正如其他人指出的那样。

问题可能出在 Cont 的使用上。在每个使用(并销毁)Cont 的 cpp 中,您必须包含 cont.h 和 inner.h。这解决了我的问题。

The forward declaration in the header is ok if you implement the destructor in the cont.cpp file and you include inner.h, as others pointed out.

The problem could be in the use of Cont. In each cpp that uses (and destroys) Cont you have to include cont.h AND inner.h. That solved the problem in my case.

饭团 2024-08-22 08:21:46

这个问题(使用私有析构函数删除对象)和这个问题(如何编写iscomplete模板)可能会对您有所帮助。

This question (deleting object with private destructor) and this question (how to write iscomplete template) may be help you.

笑,眼淚并存 2024-08-22 08:21:46

从技术上讲,您不应该用不完整的类型实例化标准库模板,尽管我知道没有任何实现是行不通的。在实践中,Sharptooth 的答案也是我推荐的。

使用裸指针作为 impl 指针实际上没有任何问题,只要您在析构函数中调用它的 delete 即可。您可能还应该实现或禁用复制构造函数和赋值运算符。

You aren't technically supposed to instantiate standard library templates with incomplete types, although I know of no implementation where this won't work. In practice, Sharptooth's answer is what I'd recommend also.

There really wasn't anything wrong with using a naked pointer for your impl pointer, as long as you call delete on it in your destructor. You should probably also implement or disable the copy constructor and assignment operator.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文