博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C++:delete不完整类型的指针
阅读量:5740 次
发布时间:2019-06-18

本文共 2340 字,大约阅读时间需要 7 分钟。

简单版

以下代码编译时会有warning:

class X;void foo(X* x) {    delete x;}

在GCC4.1.2下,编译出错信息是:

warning: possible problem detected in invocation of delete operator:warning: ‘x’ has incomplete typewarning: forward declaration of ‘struct X’note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.

这是因为在foo里,编译器看不到X的完整类型,没办法确定两件事情:

  1. X有没有自定义的析构函数(准确的说,有没有non-trivial的析构函数)。
  2. X有没有自定义的operator delete函数。

在不确定这两件事情的情况下,编译器只能按最普通的方式去处理delete x

  1. 不调用任何析构函数。
  2. 调用全局的operator delete,通常来说就是直接释放内存。

日常版

有一个我们平常会遇到的场景,就会触发上面这个问题。

以下是由三个文件组成的一个工程,其中用到了'pImpl'方法来隐藏实现,因此在接口类中放了一个std::auto_ptr,很简单:

// test.h#include 
class A { class Impl;public: A(); void Func();private: std::auto_ptr
mImpl;};// test.cpp#include "test.h"#include
class A::Impl {public: void Func() { std::cout << "Func" << std::endl; }};A::A(): mImpl(new Impl) {}void A::Func() { mImpl->Func();}// main.cpp#include "test.h"int main() { A a; a.Func();}

看起来很正常,但编译时有warning:

$g++ test.cpp main.cppIn destructor ‘std::auto_ptr<_Tp>::~auto_ptr() [with _Tp = A::Impl]’:test.h:4:   instantiated from herewarning: possible problem detected in invocation of delete operator:warning: invalid use of undefined type ‘struct A::Impl’test.h:5: warning: forward declaration of ‘struct A::Impl’note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.

和前面说的warning信息完全一致,看起来也是在调用delete时出的问题。但哪里调用了delete呢?

答案是std::auto_ptr

上面的代码中,我们没有给class A手动写一个析构函数,因为编译器自动生成的析构函数就是我们要的:析构时把mImpl析构掉。

那么自动生成的析构函数长什么样子呢?大概是:

A::~A() {    mImpl.~std::auto_ptr
();}

展开了基本就是一句delete

A::~A() {    delete mImpl._M_ptr;}

这个析构函数的位置在哪呢?C++标准里说会把自动生成的类成员函数放在类的定义中,那么就是在test.h中。

问题清楚了:我们在编译main.cpp时,看不到A::Impl的完整定义,但却有一个自动生成的A::~A,其中delete了一个不完整的类对象!

解法

手动写一个A的析构函数,位置要在能看到A::Impl完整定义的地方,也就是test.cpp:

// test.h

include

class A {

class Impl;

public:

A();~A();void Func();

private:

std::auto_ptr
mImpl;

};

// test.cpp

include "test.h"

include

class A::Impl {

public:

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

};

A::A(): mImpl(new Impl) {}

A::~A() {}

void A::Func() {

mImpl->Func();

}

## 相关文献* http://stackoverflow.com/questions/4325154/delete-objects-of-incomplete-type

转载地址:http://qcbzx.baihongyu.com/

你可能感兴趣的文章
C# 自定义控件入门
查看>>
指令 作用域绑定
查看>>
【转】web测试总结--用户体验测试
查看>>
斐波那契数列的递归实现和顺序实现
查看>>
IntelliJ IDEA 2017 主题安装及配置
查看>>
MTU设置
查看>>
gdi资料
查看>>
mysql 知识整理
查看>>
异常的定位与解决
查看>>
男人的小金库藏在哪里?——公共数据集Model
查看>>
php mysql_affected_rows获取sql执行影响的行数
查看>>
php读取zip文件(删除文件,提取文件,增加文件)实例
查看>>
理解Ajax
查看>>
mysql主从双机复制备份
查看>>
ASP.NET站点Web部署(一键发布的实现)
查看>>
各种排序_续()
查看>>
学习的第七天
查看>>
Windows 7实现自动登录(本地账户和域账户)
查看>>
spring+shiro+ehcache整合
查看>>
ssh转发流量的四种姿势
查看>>