3

假设你有这样的功能

bool verifyObject(const myObj& obj);

或者这个

bool verifyObject(const myObj obj);

据我了解,当您通过第二种情况时,会制作一份副本。但是,编译器可能会利用常量来像第一种情况一样通过。因此,我认为以任何一种方式传递 const 对象都没有区别。

我错了吗?

4

3 回答 3

3

第二个,从调用者的角度来看相当于

bool verifyObject(myObj obj);

此外,作为声明,这两个是完全等价的:

bool verifyObject(myObj obj);
bool verifyObject(const myObj obj);

所有顶级常量在函数声明中都被忽略。差异仅在定义期间表现出来

bool verifyObject(const myObj obj)
{
    obj.NonConstMethod(); //compiler error!
}

您不能修改函数内部的副本,调用者根本不关心。作为功​​能实现者,这只是出于您自己的目的。

于 2013-05-14T14:08:35.000 回答
2

据我了解,当您通过第二种情况时,会制作一份副本。

是的; 尽管在某些情况下(例如传递临时文件时),副本可能会被省略。

但是,编译器可能会利用常量来像第一种情况一样通过。

不; 除非参数是临时的,否则这不是可以省略副本的情况之一。调用函数时,编译器甚至可能不知道参数在函数内,因为在声明函数时可以省略这样const的顶层。const因此,即使它可以确定传递引用等同于传递副本(如果复制构造函数或析构函数具有可观察的副作用,或者类具有可变成员,则情况并非如此),它不能更改调用约定,因为调用者无法知道该更改。

话虽如此,如果函数是内联的,或者您的编译器进行了整个程序优化,那么这样的优化是可能的;但前提是他们不改变程序的行为。

于 2013-05-14T14:21:26.720 回答
1

对于第二个示例(按值传递), const 修饰符几乎没有什么区别,因为编译器将调用对象的复制构造函数并传递它的副本。另一方面,通过 const 引用(const myObj& obj)传递,只传递对对象的引用(不复制)。在那种情况下,被调用的函数不能通过 obj 改变对象的状态。

于 2013-05-14T14:14:25.007 回答