给出原型:
void foo(int i);
void foo(int i, const std::string &s);
实现:
void foo(int i)
{
foo(i, std::string()) ;
//! ^^^^^^^^^^^^^ ^ here?
// nothing more.
}
//! ^ here?
void foo(int i, const std::string &s)
{
//do something
}
std::string()
创建的临时对象超出范围?以这种方式过载函数是一个好习惯吗?
更新
让我解释一下这种情况。作为练习,我试图在不使用模板的情况下编写类似std::vector
的类。它拥有的唯一类型是std::string
。可以在another question中找到班级正文。
实现resize()
成员函数时,我发现std::vector
似乎正在使用两个函数:
void
resize(size_type __new_size);
void
resize(size_type __new_size, const value_type& __x);
所以我想知道我是否应该使用两个函数而不是一个函数。
答案 0 :(得分:3)
不,这不是一个好习惯,至少在这种特殊情况下。使用单个函数和参数的默认值,而不是两个函数,其中一个函数似乎只存在以提供默认参数:
void foo(int i, const std::string &s = "")
{
//do something
}
答案 1 :(得分:2)
我不认为这是不好的做法,特别是如果你使foo(int i)
内联。我可以想到这是首选的原因:当你创建指向函数的指针时,如果你声明第二个参数是default,你只能指向接受2个参数的函数。
临时值仅作为函数调用的参数。
inline void foo(int i)
{
foo(i, std::string());
}
void foo(int i, const std::string &s)
{
//do something
}
答案 2 :(得分:1)
如果函数创建了一个在函数调用本身中存活的对象,那么传递临时函数const&
的唯一“危险”就会发生,该函数调用本身会存储const&
。
想想
class A
{
const string& a;
public:
A(const string& a) :a(a) {}
void act() { .... /* use a */ }
};
A* foo(const string& s)
{ return new A(s); }
int main()
{
A* pa = foo(string());
//here, pa->act() will act on a dangling reference.
}
如果您的foo
函数只是使用字符串,但不保留引用以供以后使用,则传递临时文件是绝对安全的。
如果使用“启动功能”发生这种情况,或者默认的临时值对结果代码没有影响。
此时使用一个或两个功能更多的是风格和机会问题:两个功能在进一步开发过程中有多少机会区分?
如果答案是“无:第二个函数只是一个非常频繁的案例的定义(或快捷方式)”,那么“默认值就完全可以完成工作。”
如果答案是“让我们现在回到另一个函数,后来更具体”,那么两个函数是可取的。
默认值,但是,如果函数是模板,并且您希望类型推导工作,则不是这样的机会:
template<class C, class T>
void fn(int i, basic_string<C,T>& s = ????);
你不能使用std :: string(),因为它不适用于C
以外的char
,并且不能使用std::basic_string<C,T>()
,因为它不允许在{fn(5)
上推断1}}要求知道C和T应该是什么。
所以你最终会用
void fn(int i) { fn(i,string()); }