关于输入参数的顺序

her*_*tao 17 c c++ performance code-readability input-parameters

对于函数/方法包含许多输入参数,如果以不同的顺序传入它会有所不同吗?如果是,在哪些方面(可读性,效率......)?我更好奇我应该如何为自己的功能/方法做些什么?

在我看来,这:

  1. 通过引用/指针传递的参数通常在通过值传递的参数之前.例如:

    void* memset( void* dest, int ch, std::size_t count ); 
    
    Run Code Online (Sandbox Code Playgroud)
  2. 目标参数通常在源参数之前.例如:

    void* memcpy( void* dest, const void* src, std::size_t count );
    
    Run Code Online (Sandbox Code Playgroud)
  3. 除了一些硬约束之外,即具有默认值的参数必须是最后的.例如:

    size_type find( const basic_string& str, size_type pos = 0 ) const;
    
    Run Code Online (Sandbox Code Playgroud)
  4. 无论他们传递的是什么顺序,它们都是功能等同的(实现相同的目标).

Ton*_*roy 12

它有几个重要原因 - 如下所列.C++标准本身并没有要求在这个空间中有任何特定的行为,所以没有可靠的方式来推断性能影响,即使某个可执行文件中的某些东西(稍微)更快,程序中的任何地方或编译器都有变化选项或版本,可能会删除甚至扭转早期的好处.在实践中,听到人们谈论参数排序在性能调整中具有任何重要性是非常罕见的.如果你真的在乎你最好检查你自己的编译器输出和/或基准测试结果代码.

例外

传递给函数参数的表达式的求值顺序是未指定的,并且它很可能受到它们在源代码中出现的顺序的更改的影响,一些组合在CPU执行管道中更好地工作,或者更早地引发异常这会使一些其他参数准备短路.如果某些参数是临时对象(例如表达式的结果),这对于分配/构造和销毁/解除分配来说是昂贵的,则这可能是一个重要的性能因素.同样,对程序的任何更改都可以删除或撤消之前观察到的利益或惩罚,因此如果您关心这一点,您应该在进行函数调用之前为要先评估的参数创建一个命名临时值.

寄存器与缓存(堆栈内存)

一些参数可以在寄存器中传递,而其他参数则被推送到堆栈 - 这实际上意味着至少输入最快的CPU缓存,并暗示它们的处理速度可能较慢.

如果函数最终仍然访问所有参数,并且选择在将参数X放入寄存器和堆栈中的Y之间,或者反之亦然,那么它们如何通过并不重要,但是如果函数可能有条件影响实际使用哪些变量(如果语句,开关,可能输入或不输入的循环,提前返回或中断等),如果实际上不需要的变量在堆栈上而需要的变量是在一个登记册.

有关调用约定的一些背景和信息,请参见http://en.wikipedia.org/wiki/X86_calling_conventions.

对齐和填充

从理论上讲,性能可能会受到参数传递约定的影响:参数可能需要特定的对齐 - 或者只是全速 - 访问堆栈,编译器可能会选择填充而不是重新排序它推送的值 - 它是很难想象除非参数的数据是在缓存页面大小的范围内,否则它是重要的

非绩效因素

你提到的其他一些因素可能非常重要 - 例如,我倾向于先放置任何非const指针和引用,并将函数命名为load_xxx,因此我对可以修改哪些参数以及哪些参数的命令保持一致的期望通过他们.但是,没有特别重要的惯例.