C/C++细节笔记(不断添加ing...)

记笔记,很久没认真学习了,被别人一考就不行了,特别是一些细节,打算以后搜集一些细节的问题

1、#pragma pack(n)  的作用?

n 为1, 2, 4, 8,  16任意值,表示字节对齐,适用于通信、不同CPU的二进制兼容,许多单位喜欢面试该提

例:

#pragma pack(1)

struct{ char c; long ld;};//sizeof :char(1) + long(4) = 5

#pragma pack() //恢复原来设置

#pragma pack(2)

struct{ char c; long ld;};//sizeof :char(1)(pack(2)导致+1对齐) + long(4) = 6

#pragma pack(4)

struct{ char c; long ld;};//sizeof :char(1)(pack(4)+3对齐) + long(4) = 8

#pragma pack(8)

struct{ char c; long ld;};//sizeof :char(1)(pack(8)超过最长类型long的字节数按照pack(4)+3对齐) + long(4) = 8

如果是

#pragma pack(8)

struct{ char c; double d;};//sizeof :char(1)(pack(8)+7对齐) + double (8) = 16

2、C++的虚函数继承中子类相同函数名不加virtual 关键字还有多态性吗?

class A{ public : virtual void f();};

class B : public A{public : void f();};

A*p = (A*)new B();

p->f();//这里还有多态性,调用B::f();

3、构造函数、析构函数调用虚函数有多态性吗?

构造函数调用虚函数将丧失多态性,析购函数调用虚函数还有多态性。

4、智能指针的释放问题?

智能指针一般不需要自己释放,但是有的时候总是会有释放相关的错误:

如:我曾经这样释放

CComPtr<***> Ptr;

Ptr->Release();

这样会产生错误,因为CComPtr在析构时将在释放一次,就会产生内存访问错误;

正确的做法是Ptr.Release(); "." 和->的区别,注意,因为这里牵涉到AddRef()的应用计数,这样释放CComPtr才会知道已经被释放了,不需要在析构里释放;

我曾经写过这样的函数

void f()
{
 ::CoInitialize(NULL);
 CComPtr<IUnknown> IUPtr;
 /*
  do someing;
  */
 ::CoUninitialize();
}
 这里我以为智能指针可以自己释放,就没有.Release();谁知道CComPtr在函数里生命周期比::CoUninitialize();要长,实际的语句运行顺序是

::CoUninitialize();

CComPtr::~CComPtr();

这里CComPtr析构函数要在CoUninitialize之后运行,COM都被释放了,COM智能指针再释放当然会出错了;

所以我们要保证::CoUninitialize();最后运行,在所有与COM相关的类的生命周期结束后再被调用,特别是你采用全局的COM对象时更要注意,比如ADO中的连接_ConnetionPtr我就经常声明成全局对象,结果我在OnDestroy里::CoUninitialize();全局智能指针释放时就出错,你要做的就是在::CoUninitialize();把这些对象.Release()。

4、strstream的内存泄漏问题?

strstream在调用str()函数之后如果没有freeze()解冻内存,将会产生内存泄漏,用新版的stringstream就不会有这个问题。

 

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值