为什么`Shape * rect = Rectangle(..)`和`Shape * rect =& Rectangle(..)`不能编译,但`Shape * rect = new Rectangle(..)`呢?

时间:2014-10-03 17:23:06

标签: c++ pointers memory-management

我有一个抽象类Shape和一个子类Rectangle

我尝试创建Shape*,并为其分配一个Rectangle实例(实际上是实例的地址,因为这是一个指针.. ?)。

我试过了:

Shape* rect = Rectangle(5, 5);

得到了错误:

cannot convert from 'Rectangle' to 'Shape*' in initialization

然后我尝试了这个:

Shape* rect = &Rectangle(5, 5);

收到错误:

taking address of temporary

最后,我尝试了以下方法,并且有效:

Shape* rect = new Rectangle(5, 5);

我想了解的是,为什么这项工作和其他工作失败了?我将分享我为什么会这样做的假设,并且我希望您确认或拒绝这些假设并解释每种情况下究竟发生了什么。


我对每种情况下发生的事情的假设:

Shape* rect = Rectangle(5, 5)在堆栈上创建一个Rectangle对象(这是静态数据分配的位置..?),然后尝试将其放入{{1指针。由于Shape*是一个应该保存Shape*对象(或子类)地址的变量,因此将对象本身分配给它是没有意义的。

Shape在堆栈上创建一个Shape* rect = &Rectangle(5, 5)对象,然后尝试获取它的地址并将其放入指针中。编译器不允许这样做,因为由于该对象是匿名的,它将离开下一行(...?),并且该地址将无关紧要。

Rectangle在堆上创建一个Shape* rect = new Rectangle(5, 5)对象(存储动态数据的位置..?),然后尝试将其分配给{{1指针。我不明白为什么会这样。指针存储地址,而不是对象。为什么将对象存储在指针中是有意义的?确实它确实有效,为什么它不能在第一次尝试时起作用(即Rectangle)?


  1. 如果我写的任何内容在技术上都是错误的,请说明并解释。

  2. 请解释工作代码的工作原理和失败的代码 失败。

2 个答案:

答案 0 :(得分:4)

您的假设或多或少是正确的,但是词汇量 你使用的是令人困惑的,而在C ++中并不常见 社区。

对于初学者,表达式Rectangle(5, 5)会创建 类型为Rectangle临时。它在堆栈上,但是 重要的是它有暂时的生命;它会停止 存在于完整表达的末尾。你有时候会 这里临时称为右值;它或多或少是 在实践中也是如此。

不是静态;静态数据是具有静态的数据 一生,并没有在堆栈中。

第一个语句失败的原因是你(和编译器) 说:Rectangle不是Shape*。事实上,事实并非如此 一个指针。可能会使转换超载 运算符,以便它将隐式转换为Shape*,但是 这是一个高级主题,最好留到以后。否则,一个 类类型的实例不会转换为指针类型。

第二个语句失败,因为语言禁止 明确地取一个临时的地址。你的假设 给出了主要动机,但 还有很多方法 你可以得到一个临时的地址并搞砸了。

第三个陈述有效,因为new T的结果 expression的类型为T*(除非T是一个数组 类型 - 但从来没有任何你想new的情况 数组类型)。一个新表达式创建一个新的对象 生命周期是动态的,并返回指向它的指针;在这种情况下, 一个Rectangle*。并且来自的隐式转换 Derived*Base*

具有动态生命周期的对象通常被认为是生活在 堆。

答案 1 :(得分:2)

,因为:

Rectangle(5, 5);

返回一个Rectangle对象,但

new Rectangle(5, 5);

返回指向矩形对象的指针。

如果你想使用多态,你需要使用指针。