【问题标题】:some questions about "new" operator关于“新”运算符的一些问题
【发布时间】:2013-09-10 21:01:46
【问题描述】:

这是一个计算cpp代码的简单矩形区域,我有一些问题:

#include <iostream>
#include <conio.h>
using namespace std;
class CRectangle
{
        int *width, *heigth;
    public:
        CRectangle(int, int);
        ~CRectangle();
        int area() { return (*width * *heigth);}
};

CRectangle :: CRectangle(int a, int b)
{
    width = new int;
    heigth = new int;
    *width = a;
    *heigth = b;
}

CRectangle :: ~CRectangle()
{
    delete width;
    delete heigth;
}

void main()
{
    CRectangle rect1(3,4), rect2(5,6);
    cout << "rect1 area = " << rect1.area() << "\n";
    cout << "rect2 area = " << rect2.area();
    getch();
}
  1. 为什么在这种面向对象的代码中我们使用指针,我的意思是有什么优势?
  2. 在创建对象rect1(3,4)之后的这段代码中,我们创建rect2(5,6),这样做,逻辑上(我认为)在宽度和高度指向的内存部分中替换了5和6而不是3和4,所以 3 和 4 不再可用,但它们是

请解释到底发生了什么?

【问题讨论】:

  • 在这里使用指针绝对没有优势,还有一些非常明显的劣势。代码可能是由更熟悉不同语言(如 Java)的人编写的,其中 all 变量是使用 new 创建的。
  • 1) 使用这样的指针没有任何好处。这不是指针的好用法。 2) 您为 (5, 6) 创建/分配两个 new 整数。您没有使用旧内存。它们不重叠。他们不会覆盖。它们是完全独立的,因为每个都有自己的new 调用。
  • 由于您是新手,让我指出使用标准库的指针比使用裸指针更有帮助。例如&lt;unique_ptr&gt;&lt;shared_ptr&gt;
  • 每个 CRectangle 对象都有自己的宽度和高度指针。它们不共享。
  • 只是一个小小的挑剔...“身高”通常不拼写为“身高”...;-P

标签: c++


【解决方案1】:

1-为什么在这种面向对象的代码中我们使用指针,我的意思是有什么优势?

没有。

2、3 和 4

    width = new int;
    heigth = new int;

您总是在每个构造函数调用中保留 new 单独的内存位置。每个对象的宽度和高度都有单独的内存位置,因此不会被覆盖。

但是,在某些情况下,两个对象将共享相同的内存位置 - 如果您使用复制构造函数或赋值运算符将一个对象复制到另一个对象:

CRectangle rect1(3,4);
CRectangle rect2 = rect1;
CRectangle rect3(4, 5);
rect3 = rect1;

在这种情况下,widthheight 获得与rect1 相同的值,这将使所有三个对象都指向相同的内存位置。在rect2的情况下,不会调用默认构造函数,因此不会分配新的内存,在rect3的情况下,widthheight的旧值会丢失,变量将使用来自rect1 的内存位置进行更新,这将导致内存泄漏(因为在rect3 的默认构造函数中分配的内存将永远不会被释放)。

【讨论】:

  • 在复制其中一个对象之前不会覆盖。
【解决方案2】:

在你的情况下,指针什么也没给出。

所以指针是数组,为了证明它看运算符[] 内联实现。 a[b] 实际上是 *(a + b)。因此,如果您使用new 创建单个值(根据您的情况),这是不好的体验,您可以使用它来创建数组,在这种情况下的优势是使用new 创建内存是在堆中分配的,在 通常的方式分配的内存在堆栈中。

C++ 将此留给程序员选择是否需要指针,使用容器可以实现内存分配的优势,例如std::vector,这种方式更不容易出错。

另一件事,由于与 C 的兼容性,指针留在 C++ 中,因为有很多东西是用 C 编写的,但 C++ 开发人员也在使用它。


width和height指向的内存段中替换为5和6,而不是3和4,所以3和4不再可用

看完这句话,我想你需要了解一下 C++ 或者其他面向目标的编程语言。

我的简短解释,为什么所有值都是可访问的,rect1rect2 是完全不同的独立对象,所以它们有自己的记忆,不能相互影响。


顺便说一句:忘了提到堆中分配的缺点 - 它比堆栈中分配要慢得多。

【讨论】:

    【解决方案3】:

    为什么在这种面向对象的代码中我们使用指针,我的意思是有什么好处?

    这里没有优势...Here 是一些原因。

    有一些缺点,例如:堆上的分配比堆栈上的分配慢得多。

    在创建对象 rect1(3,4) 之后的这段代码中,我们创建了 rect2(5,6) ,这样做,逻辑上(我认为)5 和 6 被替换,而不是 3 和 4 在宽度的内存部分和高度指向 ,所以 3 和 4 不再可用,但它们是。

    不是每个创建的对象都有自己的内存空间。

    CRectangle rect1(3,4), rect2(5,6);
    

    在这里您创建了两个不同的对象。创建的第二个对象不使用第一个对象的内存。所以每个对象都有自己的空间供widthheight 成员使用。

    【讨论】:

    • 根据答案向我证明这里没有优势,但你能解释一下这在 bst tee 中的优势是什么,因为我已经看到在 bst 树中他们使用指针很多这个运算符(->)作为第二个问题,这个运算符是什么?
    • @darksky 我就是这么说的:)
    • 绝对是,但我犯了一个错误:(并编辑了我的评论,请参阅编辑后的评论:)
    • @darksky 这取决于你的 BST 树 class 是如何实现和使用的。我们无法判断它的好坏。
    • 例如在大学管理课程中添加新学生,添加新课程,显示学生状态,如通过课程和成绩等。
    【解决方案4】:

    为什么在这种面向对象的代码中我们使用指针,我的意思是有什么好处?

    据我们所知,这是您的想法。在这种情况下,如果有的话,优势是极其有限的。在这种情况下,它更有可能是一个劣势。

    在创建对象 rect1(3,4) 之后的这段代码中,我们创建了 rect2(5,6) ,这样做,逻辑上(我认为)5 和 6 被替换,而不是 3 和 4 在宽度的内存部分和 height 指向 ,所以 3 和 4 不再可用,但它们是。

    不,您误认为“逻辑上(我认为)5 和 6 被替换了”。它们都在范围内并且在 main() 块结束之前有效。

    以下是您可以使它们无效的方法:

    void main()
    {
        {
            CRectangle rect1(3,4), rect2(5,6);
        }
    
        // Note that this is no longer a valid program and will fail at compile-time
        cout << "rect1 area = " << rect1.area() << "\n";
        cout << "rect2 area = " << rect2.area();
        getch();
    }
    

    如果您的问题是如何获得rect1,然后见证rect2 的堆分配恰好发生在rect1 的位置,那么恐怕您甚至不能真正指望这种行为如果你得到它发生。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-17
      • 2013-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-25
      • 1970-01-01
      相关资源
      最近更新 更多