Effective c++ 学习笔记(item17 store newed objects in smart pointers in standalone statements.)
item17: store newed objects in smart pointers in standalone statements.
这里看四个资源管理类初始化的例子:
例子1:
int abc();
void processWidget(shared_ptr<Widget> pw, int val);
Widget *pWidget = new Widget;
shared_ptr<Widget> pw(pWidget);
processWidget(pw, abc());
这种写法不好的原因是暴露了原始资源指针pWidget, 这样后面退出函数前如果某个多事的加一句"delete pWidget;"就会导致程序崩溃。
例子2:
int abc();
void processWidget(shared_ptr<Widget> pw, int val);
shared_ptr<Widget> pw(new Widget);
processWidget(pw, abc());
这种写法是最推荐的。
例子3:
int abc();
void processWidget(shared_ptr<Widget> pw, int val);
processWidget(shared_ptr<Widget> pw(new Widget), abc());
这种写法看样子比较简洁,但是存在问题,也是不推荐的。c++对参数的处理顺序是没有定义的。上面的例子对参数的处理有三个环节:
- new widget
- shared_ptr<widget> pw构造
- abc()
因为参数的处理顺序没有定义,如果abc()发生在1,2之间,并且发生异常,就会导致资源泄露。
例子4:
int abc();
void processWidget(shared_ptr<Widget> pw, int val);
processWidget(new Widget, abc());
这个例子编译不通过。因为shared_ptr的构造器是explicit限定的,在processWidget(new Widget, abc());
语句中没有办法进行(new Widget) 对象到shared_ptr对象的自动隐式转换。
引申explicit与自动隐式转换的关系
编译器会尝试自动隐式转换的时机有两个,一个是赋值。classXX A = B;
这个句子里面如果B的类型和A的类型不一样,编译器会尝试先把B隐式转换为classXX类型。还有一个是作为函数的入参,如果函数的参数定义与传入的参数不一致,编译器也会尝试先把入参转换成定义的类型。
编译器是通过调用转换目标类的拷贝构造函数进行隐式转换的。classXX A = B;
这句话为例,编译器会调用classXX的拷贝构造函数尝试对B转换,这时候如果classXX类里面的拷贝构造函数是explicit限定,编译器的尝试就会报错。
网友评论