在C ++中的方法内创建的对象实例的持久性

时间:2011-12-12 19:54:45

标签: c++ object reference scope

假设我有一个只包含对象的简单类:

class objholder{

    object ojb;
public:
    setobj(object o);
}

objholder::setobj(object o){
    obj = o;
}

objholder::getobj(){
    return obj;
}

假设我创建了一个创建object实例的函数,然后将其传递给objholder

  • 函数返回时object的实例会发生什么?它会持续存在吗?
  • 如果我尝试访问由object保存的objholder实例,它会包含有效的引用会怎么样?

以下是一些简单的函数,用于说明我上面描述的功能。

void foo(objholder oh){
    object temp;
    oh.setobj(temp);

}
void bar(objholder oh){
    object temp = oh.getobj();
}

int main(int argc, char **argv){

    objholder o;

    foo(o);
    bar(o);
}

3 个答案:

答案 0 :(得分:3)

C ++是一种语言值语义,这意味着默认类型被视为值,复制等,而不像具有引用语义的Java或C#。让我们分析一下这个程序:

void foo( objholder );
int main(int argc, char **argv){
    objholder o;                 // [1]
    foo(o);                      // [2]
    bar(o);                      // [3]
}
void foo( objholder oh ) {       // [4]
    object tmp;                  // [5]
    oh.setobject( tmp );         // [6]
}                                // [7]

在[1]中,o范围内创建了一个新对象main。该对象包含按obj 默认构造函数初始化的类型为object子对象 objholder。在[2]中,该对象的副本完成并传递给foo([4]),创建一个传递给它的本地object([5])。 [6]中setobject的{​​{1}}成员方法,(请记住:ohohobjholder的副本),因为main按值获取元素,创建objholder::setobject的副本,并将该副本传递给tmp,然后创建副本并将其存储在成员属性中(未在代码中显示)。在[7]中,oh.setobject的执行完成,所有局部变量以创建的相反顺序销毁,这意味着foo被销毁,然后tmp(这意味着oh的内部副本被销毁。

此时我们回到tmp我们的本地对象main仍未触及 - 所有已处理的是传递给{{1}的副本 }。然后,在调用o时,会创建一个副本并传递给foo

我开始注意到这是由于C ++中的 value 语义,与其他语言中的 reference 语义相比,如Java或C#。如果程序是(语法旁边)Java,在[2]和[3]中将传递引用的副本,并且引用的对象都在foo,{{1}中和bar会是一样的。这可以通过使用指针和引用在C ++中实现。 C ++引用不仅仅是Java / C#引用,所以如果你来自任何一种语言需要时间来理解相似之处和不同之处。

答案 1 :(得分:2)

  

函数返回时object的实例会发生什么?它会持续吗?

它与持有人一起被摧毁。但请注意,您的objectholder 副本对象已传递到setobj

  

如果我尝试访问由object保存的objholder实例,它会包含有效的引用会怎么样?

你的意思是......

object obj;
{
    objectholder holder;
    holder.setobj(obj);
}
// do something to obj

?没有什么特别的事情发生(除非object在其复制构造函数中做了一些特殊的事情)。

答案 2 :(得分:1)

你完成你的objholder的方式,你不是“持有”对象,只是持有对象的副本。

这只是复制'o'并将其存储在'obj'

objholder::setobj(object o)
{
    obj = o;
}

如果你想保留对象的引用,你需要传递引用或指向对象的指针

object& obj;

objholder::setobj(object& o)
{
    obj = o;
}

然而,通过保持对象的引用,你仍然不是对象的所有者(如果我理解正确的是你得到的),你需要使用unique_ptr获取对象的所有权。通过使用unique_ptr,您可以传递一个对象。

说,为了理解对象的生命,你应该研究范围和免费存储/堆栈。