重载函数时使用临时对象作为参数是一种好的做法吗

Is it a good practice to use temporary objects as arguments when overloading functions?

本文关键字:一种 函数 临时对象 参数 重载      更新时间:2023-10-16

给定原型:

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。类主体可以在另一个问题中找到。

在实现resize()成员函数时,我发现std::vector似乎使用了两个函数:

void 
resize(size_type __new_size);
void
resize(size_type __new_size, const value_type& __x);

所以我想知道我是否应该使用两个函数而不是一个函数。

不,这不是一个好的做法,至少在这种特殊情况下是这样。使用单个函数和参数的默认值,而不是两个函数,其中一个函数似乎只提供默认参数:

void foo(int i, const std::string &s = "")
{
//do something
}

我不认为这是一种糟糕的做法,尤其是如果您使foo(int i)内联。我可以想到这样做的原因:当您创建指向函数的指针时,如果您声明第二个参数为default,则只能有指向接受2个参数的函数的指针。

临时值仅作为函数调用的参数才有效。

inline void foo(int i)
{
foo(i, std::string());
}
void foo(int i, const std::string &s)
{
//do something
}

如果函数创建了一个对象,该对象在函数调用中幸存下来,并在自身存储了const&,则传递临时的asconst&的唯一"危险"就会发生。

思考

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函数只是使用字符串,但不保留引用供以后使用,那么传递临时函数是完全安全的。

如果使用"引导函数"或默认临时值发生这种情况,则对生成的代码没有任何影响。

在这一点上,使用一个或两个函数更多的是一个风格和机会的问题:在进一步的开发过程中,这两个函数有多少机会区分开来?

如果答案是"none:第二个函数只是非常频繁情况下的定义(或快捷方式)",那么默认值就可以完美地完成任务。

如果答案是"让我们现在回到另一个函数,稍后更具体",那么两个函数是首选的。

然而,如果函数是模板,并且您希望类型推导起作用,则默认值是不可能的:

template<class C, class T>
void fn(int i, basic_string<C,T>& s = ????);

您不能使用std::string(),因为它不适用于char以外的C,也不能使用std::basic_string<C,T>(),因为它将不允许在fn(5)调用时推断C和T应该是什么。

所以你最终会得到

void fn(int i) { fn(i,string()); }

相关文章: