我是C ++的新手。请考虑以下代码:
class foo
{
int f;
public:
foo(int f1=0) : f(f1) {
cout<<"In conversion ctor\n";
}
foo(const foo & rhs) : f(rhs.f)
{
cout<<" In copy ctor\n";
}
foo& operator=(const foo & that)
{
f=that.f;
cout<<"In = optor\n";
return *this;
}
};
foo rbv()
{
foo obj(9);
return obj; //named return by value [def. 1]
}
foo caller()
{
return rbv(); // return by value [def. 2]
}
int main(void)
{
foo box=caller();
return 0;
}
没有RVO,在代码块中
foo rbv()
{
foo obj(9);
return obj;
}
foo ret= rbv();
创建'ret'时,以下步骤是否正确
(1)使用来自obj的copy ctor创建临时(比如说obj_temp), 堆栈对象'obj'被破坏,
(2)ret是从obj_temp构造的复制,obj_temp后来被销毁;
这意味着有三个对象,'obj','obj_temp'和'ret'以及两个复制ctors。
答案 0 :(得分:5)
RBV和NRBV的定义是否正确,如评论中所示?
它们是RVO和NRVO(返回值优化和命名返回值优化)
是否必须定义可访问的副本ctor,尽管在RVO期间没有调用它?
这是强制性的,编译器必须验证构造函数是否可访问,如果不是,编译器必须触发错误并且无法编译。
没有RVO,在代码块中
foo rbv() {
foo obj(9);
return obj;
}
foo ret = rbv();
现在的代码需要执行以下操作:构造函数在int
内部foo
创建obj
。将return语句中的构造复制到返回临时$tmp1
,从临时位置复制呼叫位置ret
的构造。现在,编译器可以通过在ret
之上放置返回值(根据调用约定)来删除这两个副本,因此$tmp1
和ret
是相同的内存位置,并且在同一个内存位置上构建obj
,所以最后所有三个对象都可以是一个对象,不需要执行任何副本。
答案 1 :(得分:0)