为什么写func(const Class&value)更好?

cas*_*der 4 c++ coding-style

为什么要使用func( const Class &value )而不仅仅是func( Class value )?当然,现代编译器将使用任一语法执行最有效的操作.这仍然是必要的,还是仅仅是非优化编译器时代的延续?

  • 只需添加,gcc将为任一语法生成类似的汇编代码输出.也许其他编译器不?

显然,事实并非如此.很久以前我从一些代码中得到了gcc这样做的印象,但实验证明这是错误的.信用归功于迈克尔·伯尔(Michael Burr),如果在这里给出,他对类似问题的答案将被提名.

Jar*_*Par 17

2个签名之间存在2个大的语义差异.

第一种是&在类型名称中使用.这表示该值通过引用传递.删除它会导致对象通过值传递,这将基本上将对象的副本传递给函数(通过复制构造函数).对于只需要读取数据的操作(典型的a const &),执行对象的完整副本会产生不必要的开销.对于不小或是集合的类,这种开销并不是微不足道的.

第二是使用const.这可以防止函数通过value引用意外修改值的内容.它允许调用者采取一些措施来保证函数不会突变该值.是的,在许多情况下,传递副本可以让调用者更加深入地了解这一情况.


Joh*_*ica 8

第一种形式不会创建对象的副本,它只是将引用(指针)传递给现有副本.第二种形式创建一个副本,这可能是昂贵的.这不是被优化的东西:拥有对象副本与原始副本之间存在语义差异,而复制需要调用类的复制构造函数.

对于没有复制构造函数的非常小的类(如<16字节),使用值语法而不是传递引用可能更有效.这就是你看到void foo(double bar)和不看的原因void foo(const double &var).但是为了不是微优化代码并不重要,作为一般规则,您应该通过引用传递所有实际对象,并且只传递内置类型,如值intvoid *值.


Ðаn*_*Ðаn 8

没有人提到过,存在巨大差异:对象切片.在某些情况下,您可能需要 const&(或&)获得正确的行为.

考虑另一个Derived继承自的类Class.在客户端代码中,您将创建Derived要传递给的实例func().如果有func(const Class&),那么相同的实例将被传递.正如其他人所说,func(Class)将制作副本,你将有一个新的(临时)实例Class(不Derived)func.

如果func反过来做这种差异,那么这种行为差异(不是表现)可能很重要.比较运行以下代码的结果:

#include <typeinfo.h>

struct Class
{
    virtual void Foo() {};
};
class Derived : public Class {};

void f(const Class& value)
{
    printf("f()\n");

    try
    {
        const Derived& d = dynamic_cast<const Derived&>(value);
        printf("dynamic_cast<>\n");
    }
    catch (std::bad_cast)
    {
        fprintf(stderr, "bad_cast\n");
    }
}

void g(Class value)
{
    printf("g()\n");

    try
    {
        const Derived& d = dynamic_cast<const Derived&>(value);
        printf("dynamic_cast<>\n");
    }
    catch (std::bad_cast)
    {
        fprintf(stderr, "bad_cast\n");
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    Derived d;
    f(d);
    g(d);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)