C++ 重载函数时使用临时对象作为参数是否是一种好的做法?
给定原型:C++ 重载函数时使用临时对象作为参数是否是一种好的做法?,c++,object-lifetime,C++,Object Lifetime,给定原型: 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) {
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
}
不,至少在这种情况下,这不是一个好的做法。使用单个函数和参数的默认值,而不是两个函数,其中一个函数似乎仅用于提供默认参数:
void foo(int i, const std::string &s = "")
{
//do something
}
我不认为这是一种不好的做法,特别是如果您使用
foo(inti)
inline。我可以想到这样做的原因:当您创建指向函数的指针时,如果您声明第二个参数为默认值,那么您只能拥有指向接受2个参数的函数的指针
临时值仅作为函数调用的参数处于活动状态
inline void foo(int i)
{
foo(i, std::string());
}
void foo(int i, const std::string &s)
{
//do something
}
我不认为这是一种不好的做法,特别是如果您使用
foo(inti)
inline。我可以想到这样做的原因:当您创建指向函数的指针时,如果您声明第二个参数为默认值,那么您只能拥有指向接受2个参数的函数的指针
临时值仅作为函数调用的参数处于活动状态
inline void foo(int i)
{
foo(i, std::string());
}
void foo(int i, const std::string &s)
{
//do something
}
传递临时asconst&
的唯一“危险”是,如果函数创建的对象在函数调用本身之后仍然存在,并且在函数调用本身中存储了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 = ????);
.传递临时as常量&
的唯一“危险”是,如果函数创建的对象在函数调用本身之后仍然存在,并且在函数调用本身中存储了一个常量&
考虑
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()
而不是“
”,以防实现碰巧为空文本分配内存。@meagar Hi!我已经更新了线程。我同意他不需要重载,但如果提供了默认参数,此解决方案中仍然存在临时对象。在这种情况下,它似乎确实存在。您可能想说std::string()
,而不是“
”,以防实现为空文本分配内存。@meagar Hi!我已经更新了线程。我同意他不需要重载,但是如果提供了默认参数,这个解决方案中仍然存在临时对象。如果不理解预期的语义,就不可能给出一个好的答案。如果两个foo
都做了同样的事情,给它们取相同的名字是有意义的,那么为什么取较少参数的一个需要调用取较多参数的一个,然后再做更多的事情呢?这些东西是琐碎的(日志记录?)还是界面的可见部分,比如一个foo
做了一些外部理解为与另一个不同的事情?通过编辑,关于生存期的问题没有多大意义。@DavidSchwartz Hi我已经更新了线程。希望它能使情况更清楚。如果不理解预期的语义,就不可能给出一个好的答案。如果两个foo
都做了同样的事情,给它们取相同的名字是有意义的,那么为什么取较少参数的一个需要调用取较多参数的一个,然后再做更多的事情呢?这些东西是琐碎的(日志记录?)还是界面的一个可见部分,比如一个foo
做一些事情