C++编程规范指46:如果提供专门的new,应该提供所有标准形式(普通、就地和不抛出)
2014-02-23 21:09
357 查看
摘要:
不要隐藏好的new:如果类定义了operatornew 的重载,就应该提供operator new 所有三种形式——普通(plain)、就地(in-place)和不抛出(nothrow)的重载。
很少需要提供自定义的new 或者delete,但是如果确实需要,通常也不想隐藏内置的签名。
C++中,在某个作用域(比如一个类作用域)里定义了一个名字之后,就会隐藏所有外围作用域中(如,在基类或者外围名字空间)同样的名字,而且永远不会发生跨作用域的重载。当上述名字是operator new时,需要特别小心,以免对类的客户产生不良影响。
假设我们定义了一个类专门的operatornew:
Class C
{
//……
Static void* operatornew(size_t,void*);//隐藏三种常规形式
};
然后,如果有人试图编写一个和普通旧式newC一样无趣的表达式,编译器会拒绝对其进行编译,其根据是无法找到普通旧式的operator new。生命接受一个memorypool为参数的C::operator new重载,将隐藏所有其他重载,包括我们都熟知而且爱用的内置全局版本,也就是:
Void* operatornew(std::size_t);//普通new
Void* operatornew(std::size_t,std::nothrow_t) throw();//不抛出new
Void* operatornew(std::size_t,void*);//就地new
或者,类也可能对以上三种operatornew 之一提供自己专用的版本。在此情况下,如果声明了其中之一,默认时类将屏幕其他两个:
Class C
{
//……
Static void* operatornew(size_t,void*);//隐藏其他两种常规形式
};
应该让类C在作用域中显式地声明operatornew 的所有三种标准变体。通常,所有三种形式都有相同的可见性。(各个形式还可以将可见性设为private,比如要显示地禁用普通或者不抛出operator new,但是本条款的目的是提醒读着记住不要因为疏忽而隐藏它们。)
请注意,应该总是避免就地new,因为它在STL容器中有广泛的使用。
最后一个技巧是:在两种不同的环境下,公开已隐藏的operator new需要采用来年各种不同的方式。如果类的基类也定义了operator new,那么要公开operator new所需做的就是:
Class C:public B
{
//……
Public:
Using B::operator new;
};
否则,如果没有基类版本或者基类没有定义operatornew,就需要写一些短小的转送函数(因为无法通过using从全局名字空间中导入名字):
Class C
{
//……
Public:
Static void* operator new(std::size_t s)
{
Return ::operator new(s);
}
Static void* operator new(std::size_t s,std::nothrow_t nt) throw()
{
Return ::operator new(s,p);
}
};
上面的建议也适用于数组形式的operatornew[]和operator delete[]。
避免在客户代码中国调用new(nothrow)版本,但是仍然要为客户提供,以免客户一旦要用到时感到奇怪。
不要隐藏好的new:如果类定义了operatornew 的重载,就应该提供operator new 所有三种形式——普通(plain)、就地(in-place)和不抛出(nothrow)的重载。
很少需要提供自定义的new 或者delete,但是如果确实需要,通常也不想隐藏内置的签名。
C++中,在某个作用域(比如一个类作用域)里定义了一个名字之后,就会隐藏所有外围作用域中(如,在基类或者外围名字空间)同样的名字,而且永远不会发生跨作用域的重载。当上述名字是operator new时,需要特别小心,以免对类的客户产生不良影响。
假设我们定义了一个类专门的operatornew:
Class C
{
//……
Static void* operatornew(size_t,void*);//隐藏三种常规形式
};
然后,如果有人试图编写一个和普通旧式newC一样无趣的表达式,编译器会拒绝对其进行编译,其根据是无法找到普通旧式的operator new。生命接受一个memorypool为参数的C::operator new重载,将隐藏所有其他重载,包括我们都熟知而且爱用的内置全局版本,也就是:
Void* operatornew(std::size_t);//普通new
Void* operatornew(std::size_t,std::nothrow_t) throw();//不抛出new
Void* operatornew(std::size_t,void*);//就地new
或者,类也可能对以上三种operatornew 之一提供自己专用的版本。在此情况下,如果声明了其中之一,默认时类将屏幕其他两个:
Class C
{
//……
Static void* operatornew(size_t,void*);//隐藏其他两种常规形式
};
应该让类C在作用域中显式地声明operatornew 的所有三种标准变体。通常,所有三种形式都有相同的可见性。(各个形式还可以将可见性设为private,比如要显示地禁用普通或者不抛出operator new,但是本条款的目的是提醒读着记住不要因为疏忽而隐藏它们。)
请注意,应该总是避免就地new,因为它在STL容器中有广泛的使用。
最后一个技巧是:在两种不同的环境下,公开已隐藏的operator new需要采用来年各种不同的方式。如果类的基类也定义了operator new,那么要公开operator new所需做的就是:
Class C:public B
{
//……
Public:
Using B::operator new;
};
否则,如果没有基类版本或者基类没有定义operatornew,就需要写一些短小的转送函数(因为无法通过using从全局名字空间中导入名字):
Class C
{
//……
Public:
Static void* operator new(std::size_t s)
{
Return ::operator new(s);
}
Static void* operator new(std::size_t s,std::nothrow_t nt) throw()
{
Return ::operator new(s,p);
}
};
上面的建议也适用于数组形式的operatornew[]和operator delete[]。
避免在客户代码中国调用new(nothrow)版本,但是仍然要为客户提供,以免客户一旦要用到时感到奇怪。
相关文章推荐
- 编写一个程序,从标准输入读取字符,并把它们写到标准输出中。除了大写字母字符要转化为小写字母之外,所有字符的输出形式应该和他的输入形式完全相同
- effective C++笔记之条款9、10:避免隐藏标准形式的new、如果写了operator new 就要同时写operator delete
- 从标准输入读取C源码,并验证所有花括号都正确地成对出现。只检查其是否成对出现,不考虑其出现形式。
- 常捕获与抛出地疑难,啥时候应该try,啥时候应该throws,有无一个标准或者标准?
- Effective C++ 第二版 8) 写operator new 和operator delete 9) 避免隐藏标准形式的new
- IOS调用WCF提供的服务方法,但是方法的参数是WCF那边自定义的对象,这样有办法调用么,如果可以IOS应该怎么传参呢?请问有了解的么,
- Effective C++ 第二版 8) 写operator new 和operator delete 9) 避免隐藏标准形式的new
- 如果希望给Android客户端提供JSON格式的数据,服务端应该用什么技术编写呢?
- Linux下统计文件行数 语法:wc [选项] 文件… 说明:该命令统计给定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所有 指定文件的总统计数。字是由空格字符
- 条款9:避免隐藏标准形式的new
- Effective C++ 条款15、16 在资源管理类中提供对原始资源的访问||成对使用new 与 delete要采取相同形式
- Effective C++:条款9: 避免隐藏标准形式的new
- C++编程规范之28:优先使用++和—的标准形式。优先调用前缀形式
- 编写一个程序,从标准输入读入字符,并把它们写出在标准输出中。 所有非字母字符都完全按照它的输入形式输出,字母字符在输出前进行加密
- Android 如果公司里面要你提供一份购买测试机的清单,你应该如何提供呢?
- 条款九: 避免隐藏标准形式的new
- C++编程规范之45:总是一起提供new和delete
- operator new之避免覆盖标准形式的new/delete的“模板”类
- 条款16:成对使用new和delete时形式应该相同
- 建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内 如果需要在循环中引发异常,你需要特别注意,应为抛出异常是一个相当影响性能的过程。应该尽量在循环当中对异常发生的一