foo和bar之间有区别:
class A
{
Object __o;
void foo(Object& o)
{
__o = o;
}
void bar(Object o)
{
__o = o;
}
}
据我了解,foo在调用对象o时不执行复制操作,并且对赋值执行一次复制操作。 Bar在调用对象o时执行一次复制操作,而另一个用于赋值。所以我或多或少会说foo使用的内存比bar少2倍(如果o足够大)。这是对的吗?
编译器是否可以优化bar函数以仅对o执行一次复制操作?即使__o指向参数o的本地副本而不是创建新副本?
答案 0 :(得分:6)
这取决于。例如,如果编译器决定内联函数,显然没有副本,因为没有函数调用。
如果你想确定,请通过const-reference:
void bar(const Object& o)
这不会复制。请注意,非const版本需要左值,因为引用是可变的。 foo(Object())
不起作用,但临时值(rvalues)可以绑定到const-reference。
顺便提一下,标识符中的双下划线是为编译器保留的。
答案 1 :(得分:0)
由于赋值通常需要const Something&
作为参数,因此编写规范是正常的:
void foo(const Object& o)
{
__o = o;
}
但是这并没有回答你关于优化的问题。我不确定,一般来说,编译器可以/将会进行这样的优化。
答案 2 :(得分:0)
我认为可以说foo()
执行的副本比bar()
少一个。说消耗多少或多少内存并不是很有意义,因为对于简单的对象,它们存储在堆栈中并在从bar()
返回后进行清理。
如前所述,请勿在标识符的开头使用下划线。
答案 3 :(得分:0)
我认为编译器可以在临时对象的情况下进行优化。这种技术称为复制省略。
请参阅我发布的what-is-copy-elision-and-how-it-optimizes-copy-and-swap-idiom问题的答案。这个ans非常有帮助What is copy elision and how does it optimize the copy-and-swap idiom?
虽然我不是这方面的专家,但据我所知,编译人员可以在某些情况下优化临时对象的复制。
例如,如果您的代码是这样调用的
bar(getObject())
其中getObject
有签名
Object getObject()
此调用将导致创建Object
类型的临时值。如果编译器没有进行任何优化,则必须将temporay复制到bar
的参数中。
但是,如果编译器支持复制省略,则不会执行此复制,并且临时将作为参数传递给bar
函数。因此避免了副本,其性能与接受引用的foo
相同。但正如我所说,它仅在临时对象的情况下发生