4

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# 中的示例是可以的,因为只要有对它的引用,匿名新人就会留在范围内。(调用函数得到一个。)

我做对了吗?

4

7 回答 7

4

C++ 中的示例不正确,因为“p”将超出范围,并且函数将返回无效指针。

正确的。

C# 中的示例没问题,因为只要有对它的任何引用,匿名的“新人”就会留在范围内。

这或多或少是正确的,但您的术语并不完全正确。C# 中的范围是可以使用非限定名称的文本区域。此处的对象没有名称。生命周期是保证存储位置有效的运行时间。 范围和生命周期是相连的;当控制离开与范围关联的代码时,通常允许在该范围内声明的本地人的生命周期结束。(在某些情况下,本地人的生命周期比控制在其范围内的时间更长或更短。)

另外,请注意,它不是对 Person 对象的任何引用使其保持活动状态。引用必须是root的。你可以有两个相互引用但无法访问的 Person 对象;每个人都有参考的事实并不能让他们保持活力;其中一个引用必须是植根的。

于 2011-12-10T15:47:07.097 回答
2

此示例中的范围规则是类似的,但在 C# 中,如果将返回的值分配给某物,那么只要某物持有对它的引用,它就不会被垃圾收集。如果它没有分配给某物,则没有任何东西持有对它的引用,它将在下次收集器执行时被垃圾收集

于 2011-12-10T12:01:16.923 回答
2
person* NewPerson(void)
{
  person p();
  /* ... */
  return &p; //return pointer to person.
}

p不是一个person,看最头疼的解析。因此,您会收到编译器错误。

其余的,是的,你是对的。

于 2011-12-10T12:02:15.973 回答
1

在 C++ 中,'p' 将存在于堆栈中,因此在函数返回时会被破坏。在 C# 中,垃圾收集器知道在最后一个引用丢失之前不会破坏它。

(“clobber”在这里被松散地使用......:p)

于 2011-12-10T12:01:05.190 回答
1

是的,你没看错。

但是,在 C++ 中,你真的会这样做

person NewPerson()
{
  person p;
  /* ... */
  return p; //return person.
}

并且很确定在通话中

person x = NewPerson();

编译器将优化返回值的复制。

于 2011-12-10T12:16:54.137 回答
0

我做对了吗?

是的。

顺便说一句:在 C++ 中人 p(); 声明一个函数并且不会调用 person 的默认 ctor。只需写人 p;

于 2011-12-10T12:02:45.020 回答
0

这在 C++ 中不起作用,因为您正在返回对临时对象的引用,该临时对象将在函数结束后被销毁。您需要new在堆上创建一个人,然后返回对其的引用。

于 2011-12-10T12:02:49.937 回答