假设你有这样的功能
bool verifyObject(const myObj& obj);
或者这个
bool verifyObject(const myObj obj);
据我了解,当您通过第二种情况时,会制作一份副本。但是,编译器可能会利用常量来像第一种情况一样通过。因此,我认为以任何一种方式传递 const 对象都没有区别。
我错了吗?
第二个,从调用者的角度来看相当于
bool verifyObject(myObj obj);
此外,作为声明,这两个是完全等价的:
bool verifyObject(myObj obj);
bool verifyObject(const myObj obj);
所有顶级常量在函数声明中都被忽略。差异仅在定义期间表现出来
bool verifyObject(const myObj obj)
{
obj.NonConstMethod(); //compiler error!
}
您不能修改函数内部的副本,调用者根本不关心。作为功能实现者,这只是出于您自己的目的。
据我了解,当您通过第二种情况时,会制作一份副本。
是的; 尽管在某些情况下(例如传递临时文件时),副本可能会被省略。
但是,编译器可能会利用常量来像第一种情况一样通过。
不; 除非参数是临时的,否则这不是可以省略副本的情况之一。调用函数时,编译器甚至可能不知道参数在函数内,因为在声明函数时可以省略这样const
的顶层。const
因此,即使它可以确定传递引用等同于传递副本(如果复制构造函数或析构函数具有可观察的副作用,或者类具有可变成员,则情况并非如此),它不能更改调用约定,因为调用者无法知道该更改。
话虽如此,如果函数是内联的,或者您的编译器进行了整个程序优化,那么这样的优化是可能的;但前提是他们不改变程序的行为。
对于第二个示例(按值传递), const 修饰符几乎没有什么区别,因为编译器将调用对象的复制构造函数并传递它的副本。另一方面,通过 const 引用(const myObj& obj)传递,只传递对对象的引用(不复制)。在那种情况下,被调用的函数不能通过 obj 改变对象的状态。