可选参数的性能与可读性

Performance vs Readability with optional parameter

本文关键字:可读性 性能 参数      更新时间:2023-10-16

假设我必须为类中包含的向量的每个成员调用相同的方法
如果向量的元素-i有一个特定的值,我必须修改它。
我在这个向量中有最大10元素。

最好的方法是什么
-是否使用可选参数调用方法
-或者调用内部带有if-else语句的方法?

class A {   
  public:    
   A();   
   void doSomething(const string& s) {   
      if(s=="foo") {  
        std::cout << s;   
      } else {   
        std::cout << s << ".dat"   
      }   
    }    
    void doSomethingDef(const string& s, const string& v = "")  {   
      std::cout << s << v;   
    }      
  private:   
    std::vector<std::string> list_;      
}  
int main() {   
  A a;  
}  

/* Constructor with method 1 */   
A::A() {    
 std::vector<std::string>::iterator i = list_.begin();     
 for(; i != list_.end(); ++i) {    
   this->doSomething(*i);    
 }     
}   
/* Constructor with method 2 */   
A::A() {    
   this->doSomethingDef(list[0]);   
   this->doSomethingDef(list[1]);   
   this->doSomethingDef(list[2]);  
   this->doSomethingDef(list[3]);    
   this->doSomethingDef(list[4], ".dat");  
   this->doSomethingDef(list[5], ".dat");  
   this->doSomethingDef(list[6]);  
   this->doSomethingDef(list[7]);  
   this->doSomethingDef(list[8]);  
   this->doSomethingDef(list[9]);  
}   

如果您最多有10个元素,我将声称性能无论如何都是完全无关的。

此外,在您证明性能确实很重要之前,方法1的可读性要高得多,因此您应该更喜欢它。

最后,由于cout操作的工作方式,我想在这个小例子中,方法2实际上更慢,因为它比对格式化的输出函数进行额外调用更快地执行分支和与固定字符串的比较。

在C++11中,方法1的构造函数可以写成:

A::A()
{
    for(const auto & listElement : list_)
    {
        this->doSomething(listElement);
    }
}

性能和可读性以及更通用的引导。或者,您可以使用std::for_each和lambda函数来完成此操作,该函数可能会触发启用了优化的编译器来为您展开该循环。

A::A()
{
    for_each(begin(list_), end(list_),[this](const std::string & listElement)
    {
        doSomething(listElement);
    });
}

如果你决定使用类似于第二种方法的方法(我并不是建议你这样做,只是考虑如果你这样做的话如何),我会强烈考虑使用重载而不是默认参数:

void doSomethingDef(const string& s)  {   
  std::cout << s;   
}
void doSomethingDef(const string &s, const string &v) {
   std::cout << s << v;
}

对于默认参数,您仍然要创建一个临时字符串并将其作为第二个参数传递,然后进行所有iostreams调用以将该字符串插入流中,即使它没有效果。通过使用重载,您可以避免创建、传递和插入第二个字符串所需的所有处理(当然,除非您确实有第二个要显示的字符串)。

将其与I/O混合在一起(无论如何只写10个字符串)可能会掩盖其中的大部分好处,因此可能很难衡量,更不用说在现实生活中注意到了。另一方面,如果您生成了很多字符串,并且(例如)将输出存储在内存中,而不是将其写入输出,那么差异可能会开始变得很大。