C ++代码:
person* NewPerson(void)
{
person p;
/* ... */
return &p; //return pointer to person.
}
C#代码:
person NewPerson()
{
return new person(); //return reference to person.
}
如果我理解这一点,那么C ++中的示例就不行了,因为p
会
超出范围,函数将返回一个野指针(悬空指针)。
C#中的示例没问题,因为只要有对它的引用,匿名新人就会留在范围内。 (调用函数得到一个。)
我做对了吗?
答案 0 :(得分:4)
C ++中的示例不正常,因为'p'将超出范围,并且该函数将返回无效指针。
正确。
C#中的示例是可以的,因为只要有任何对它的引用,匿名“new Person”就会保留在范围内。
这或多或少是正确的,但你的术语并不完全正确。 C#中的范围是可以使用非限定名称的文本区域。这里的对象没有名称。 生命周期是运行时间段,在此期间保证存储位置有效。连接范围和生命周期;当控件离开与作用域关联的代码时,通常允许在该作用域内声明的本地生命周期结束。 (有些情况下,当地人的生命时间比控制在他们的范围内的时间更长或更短。)
另请注意,它不是对Person对象的任何引用,使其保持活动状态。引用必须是 rooted 。你可以有两个Person对象相互引用但是无法访问;每个人都有参考的事实并不能让他们活着;其中一个参考文献必须扎根。
答案 1 :(得分:2)
此示例中的作用域规则是类似的,但在C#中,如果返回的值被分配给某个东西,那么只要某个东西持有对它的引用,它就不会被垃圾收集。如果它没有分配给某个东西,那么什么都没有引用它,并且下次收集器执行时它将被垃圾收集
答案 2 :(得分:2)
person* NewPerson(void)
{
person p();
/* ... */
return &p; //return pointer to person.
}
p
不是person
,请参阅most vexing parse。因此,您将收到编译器错误。
其余的,是的,你是对的。
答案 3 :(得分:1)
在C ++中,'p'将存在于堆栈中,因此在函数返回时会被破坏。在C#中,垃圾收集器知道在最后一个引用丢失之前不会破坏它。
('clobber'在这里松散地使用......:p)
答案 4 :(得分:1)
是的,你做得对。
然而,在C ++中,你真的会喜欢这个
person NewPerson()
{
person p;
/* ... */
return p; //return person.
}
并且非常肯定在通话中
person x = NewPerson();
编译器将优化复制返回值。
答案 5 :(得分:0)
我做对了吗?
是
BTW:在C ++中的人p();声明一个函数,不会调用默认的ctor。只写人p;
答案 6 :(得分:0)
这在C ++中不起作用,因为您返回对临时的引用,一旦该函数结束就会被销毁。您需要在堆上创建一个new
人,然后返回对该人的引用。