首页天道酬勤c语言中有string类型吗(c语言中有没有布尔类型)

c语言中有string类型吗(c语言中有没有布尔类型)

admin 12-21 02:19 277次浏览

在delete中删除仅未定义声明的类型的指针是很危险的。 这样,就不能调用对象本身的析构函数、成员/基类的析构函数等析构函数,资源经常会泄漏。

示例代码:

引用:

c类; //在其他cpp文件中定义

c *创建(; //在其他cpp文件中定义

int主()。

c * p=创建(;

删除; //资源流失

}初始分析:由于未定义类型c,因此无法找到析构函数的原型。 (析构函数没有返回类型和参数,但这些信息不足以确定整个析构函数的原型。 例如,析构函数是私有的吗? 析构函数是虚拟的吗? 这些信息目前尚不明确)。 另外,我也不知道这个类是否重载了operator delete,但是最后的delete p实际上被编译了。

这样的结果令人困惑。 为什么即使在不知道这么多信息的情况下,delete p也能通过编译呢? 其实也有一点容易理解的情况:

引用:

c类;

CcreateC (;

int主()。

Crc=createC (;

C*p=rc; 使用操作器

}这里使用的是c :操作器。 根据c语法,如果未定义c :操作器,编译器将自动生成它。 如果定义了c 3360:操作器,编译器不再自动生成。 由于此处未定义类型c,因此不知道是否定义了c :操作器,但此代码可以通过编译。 实际行为似乎未定义c :操作器。 也就是说,即使用户定义了“在其他地方”C:operator,编译器也看不到,但在这里必须使用,所以会自动生成operator。

回顾之前的delete p,可以理解。 编译器没有看到C:~C ()、C:~C操作者删除,因此程序员认为没有定义这些内容。 对于析构函数,编译器本来应该在调用析构函数之前调用基类的析构函数和成员的析构函数,但现在无法确定基类和成员,所以只能调用。 对于operator delete,编译器没有看到它,因此将其视为不存在。

因此,只释放了指针指向的内存,不再调用析构函数和基类及其成员的析构函数。 也就是说,上例中的delete p实际上是delete(void* ) p。 后者写法的危险性显而易见。

你可能觉得这种情况很傻,但很少遇到。 在设计中,接口通常是成对提供的。 例如,如果有createC,就应该有destroyC。 但是,如果设计疏忽,上面的代码没有编译错误,最终就会出现问题。 VC6会发出警告,但操作者不会发出警告。

但是,有些设计师可能会提供“std:auto_ptrC createC ()”,创建对象,在不需要时将其丢弃。 由于std:auto_ptr内部仍然是调用的delete,所以问题依然存在,嵌入得更深。

使用boost:shared_ptr的话情况会变好。 如果main函数在a文件中,createC函数在b文件中,则对于std:auto_ptr来说,析构函数实际上是在a文件中调用delete,而在a文件中则是class C 但是,在Boost:3360shared_ptr中,由于在构建时将delete作为“删除器”传递到Boost33603360shared_ptr内部,因此在构建时实际上调用b文件内的delete

如果将class C析构函数定义为private,则仍可以编译std:auto_ptr的版本,但boost:shared_ptr的版本会发生错误。

要了解“当前编译的文件中是否存在某种类型的定义”,请使用sizeof。 根据编译器的不同,如果对未定义的类型执行sizeof,则为0 (、VC系列如果对未定义的类型执行sizeof,则为编译错误。 为了统一接口,请使用boost_static_assert(sizeof(c )=0); 或者在未安装boost的情况下直接使用staticconstchararr[sizeof(c ) ];

如果使用boost:checked_delete而不是delete (当然还有一个boost 3360: checked _ array _ delete ),则检查是否已经定义了类型如果未定义,则会发生编译时错误,如果已定义,则直接执行delete操作。

最奇怪的是,如果未定义类,则并非所有操作者都按照“编译器默认生成的操作”进行操作,例如使用operator=会导致编译错误。

引用:

c * p=创建(;

*p=*p; //编译错误。 operator=不自动生成总结:

使用已声明但未定义的“不完整类型”时,需要特别注意。 其析构函数、operator delete、operator等按编译器的缺省方式运行,因为它们在另一个文件中有定义,但在此文件中没有定义。 最危险的是忽略自定义析构函数。

由于智能指针(如std:auto_ptr )内部实际上也使用了delete,因此必须使用它来显示类定义。 必须避免这样的设计。 c类; STD :自动_ PTRC创建(;

对于操作者,最好的方法是不重载。

最后,如果想学习C/C的话,请通过私信小编“01”获取素材资料、开发工具和听课权限哦。

沙箱技术 进程安全(什么是沙箱安全机制)C#二进制序列化实例分析SpringBoot怎么整合Thymeleaf与FreeMarker视图层技术
() google手机地图打不开(onedrive离线文件路径)
相关内容