2011-05-16 64 views
4

我是C++的新手。请考虑下面的代码:在C++中创建没有RVO的对象和副本ctors

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; 
} 
  1. 是RBV和NRBV正确的定义如 评论指出?
  2. 虽然在RVO期间没有调用 ,但它是否需要定义可访问的副本?
  3. 没有视网膜静脉阻塞,在代码块

    foo rbv() 
        { 
        foo obj(9); 
        return obj; 
        } 
    
        foo ret= rbv(); 
    

是在创造 'RET'

(1)临时(比如obj_temp)创建使用拷贝构造函数的正确执行以下步骤从obj, 堆栈对象'obj'被销毁,

(2)ret是从obj_temp构造的复制,obj_temp后来销毁;这意味着有三个对象'obj','obj_temp'和'ret'以及两个拷贝参与者。

+1

你运行它时看到了什么文字?它确认你的猜测吗? – dlev 2011-05-16 20:09:49

+2

如果您不熟悉C++,那么您应该关注的东西比RVO更多。大多数(可能90%以上)的课程都不应该是可复制的。 – 2011-05-16 20:18:22

+0

def。 1是NRVO,def。 2是RVO,Q中缺少'O'和一些错别字。 @dlev没有优化,只考虑NRVO和调用rbv()而不是调用者(),1个转换器,调用2个副本。这证实了我的猜测。只有优化转换ctor被调用。 – Burt 2011-05-16 23:03:39

回答

0
  1. 看起来是对我的。
  2. 如果您要复制对象,则必须定义可访问的复制构造函数。即使副本可以被优化掉。
  3. 这听起来是对的,尽管精确的排序可能是实现定义的。您必须
5

RBV和NRBV的定义是否正确,如注释中所示?

他们是RVO和NRVO(返回值优化和命名返回值优化)

是否必须有定义,虽然它不RVO中调用的可访问副本构造函数?

这是强制性的,编译器必须验证构造函数是否可访问,如果它们不是,编译器必须触发错误并且无法编译。

没有视网膜静脉阻塞,在代码块

foo rbv() { 
    foo obj(9); 
    return obj; 
} 
foo ret = rbv(); 

的代码,因为它代表需要以下操作:构造服用intfoo创建obj。将退货声明中的施工复制到临时退货$tmp1,在临时地点复制施工地点ret。现在,编译器可以通过在ret的顶部放置返回值(根据调用约定)来取消两个副本,所以$tmp1ret是相同的存储器位置,并且通过在同一存储器位置上构造obj,所以在结束所有三个对象可以是单个对象并且不需要执行副本。