在Scott的有效C++中,他提供了隐式转换和RAII类使用不当的一个例子:
class Font { // RAII class
public:
explicit Font(FontHandle fh) // acquire resource;
: f(fh) // use pass-by-value, because the
{} // C API does
~Font() { releaseFont(f ); } // release resource
... // handle copying (see Item14)
private:
FontHandle f; // the raw font resource
};以及隐式转换函数:
class Font {
public:
...
operator FontHandle() const // implicit conversion function
{ return f; }
...
};他还举例说明了这种糟糕的用法:
Font f1(getFont());
...
FontHandle f2 = f1; // oops! meant to copy a Font
// object, but instead implicitly
// converted f1 into its underlying
// FontHandle, then copied that下面是他说的话:
现在,程序有一个由字体对象f1管理的FontHandle,但是FontHandle也可以作为f2直接使用。那几乎从来都不是好事。例如,当f1被销毁时,字体将被释放,和f2将悬挂。
为什么f2会摇摇晃晃?将包含在FontHandle中的f1资源复制到f2之后,f2和f1将是完全独立的对象。那么,如果我们发布f1,它将如何影响f2?我们使用复制,而不是moving。
发布于 2015-07-18 04:51:11
FontHandle最终是一个指针本身。f2是RAII类外部指针的副本。当f1超出作用域时,它将释放f1...but f2中的字体指向的内存。
为了清晰起见,使用了"FontHandle“名称,但是很多时候,为了分离和隐藏实现,这些API函数需要一个类似于void指针(void*)的东西,只有API的内部才有取消引用和使用的信息。然后,他们可能会执行类似于typedef void *FontHandle的操作,这样您就可以知道虚空指针在语义上代表了什么。
发布于 2015-07-18 04:52:58
假设FontHandle是一个指针,那么f2和私有成员f1.f将指向同一件事情。如果f1不再存在(例如超出作用域或显式释放),那么f2将是一个悬空指针。
发布于 2015-07-18 04:54:58
注意转换函数:
operator FontHandle() const // implicit conversion function
{ return f; }每当您需要将Font转换为FontHandle时,只需返回获取的句柄。F2本身就是这个对象,而不是副本。C++希望你自己在这里复制一份。此外,
当你做的时候
FontHandle f2 = f1; // oops! meant to copy a Font这就调用了上面的操作符。它不调用复制构造函数。为什么?
t1 = t2;语句等效于:
t1.operator=(t2);因为您还没有定义上面的内容,所以就像上面定义的那样,隐式转换。复制构造函数只有在执行以下操作时才会被调用。
Font f2 = f1;https://stackoverflow.com/questions/31487869
复制相似问题