【问题标题】:Creating a C++ object with and without new keyword创建带有和不带有 new 关键字的 C++ 对象
【发布时间】:2020-09-18 15:38:28
【问题描述】:

使用 new 关键字创建对象:

#include <iostream>
#include <string>

using namespace std;

class Person {
  private:
  string name;

  public:
  Person(string name) {
    setName(name);
  }

  string getName() {
    return this->name;
  }

  void setName(string name) {
    this->name = name;
  }
};

int main() {
  Person *person1 = new Person("Rajat");
  Person *person2 = person1;

  person2->setName("Karan");

  cout << person1->getName() << endl;
  cout << person2->getName() << endl;

  return 0;
}

输出:

Karan  
Karan

创建一个没有 new 关键字的对象:

#include <iostream>
#include <string>

using namespace std;

class Person {
  private:
  string name;

  public:
  Person(string name) {
    setName(name);
  }

  string getName() {
    return this->name;
  }

  void setName(string name) {
    this->name = name;
  }
};

int main() {
  Person person1("Rajat");
  Person person2 = person1;

  person2.setName("Karan");

  cout << person1.getName() << endl;
  cout << person2.getName() << endl;

  return 0;
}

输出:

Rajat  
Karan  

我希望输出是“Karan Karan”,正如我在Person person2 = person1 中所想的那样,person2 指的是相同的person1。但事实并非如此。

有人可以解释一下Person person2 = person1 行在幕后做什么吗?它会创建一个全新的对象吗?

【问题讨论】:

  • 很好的问题,因为您已经强调了新手对 C++ 的一个非常重要的误解。 Person person2 = person1; 复制一个人对象。 person1 和 person2 绝对不是指同一个对象。它们是不同(但相等)的对象。我确实感到惊讶的是,如此多的新手假设相反。除了可能使用其他语言的经验之外,我能想到的这种假设没有任何根据。
  • 如果您能够清楚地了解复制引用和复制值之间的区别,那么您将克服新手在理解 C++ 时遇到的许多问题。
  • @john-我也是 C++ 新手,并且来自 Java 背景,所以有点困惑。并感谢您欣赏我的问题:)
  • @john - 更公平的说法是,当新手之前学习过一些其他语言时,他们对 C++ 有误解。我遇到过不少人将 C++ 作为他们的第一语言来学习,他们中没有人有过这样的误解。其他一些语言,如 Java、Eiffel(不胜枚举)默认引用语义,我还没有遇到一个对 C++ 有“误解”的人,他没有这些语言的背景,只是假设没有检查 C++ 是否可以作为他们以前学过的语言来工作
  • @Peter 我的观点基于我在这里看到的问题,不幸的是新手通常不会解释自己,但我认为这种误解比你建议的要普遍。我并不是说新手有一个连贯的理解,只是碰巧是错误的(但 Karan 似乎是一个例外),而是他们对复制的实际含义、价值或参考感到困惑。新手通常对此没有一致的想法。

标签: c++ class c++17 dynamic-memory-allocation copy-constructor


【解决方案1】:

让我们看看后台发生了什么。

第一种情况

  • 在使用 new 关键字时,new 创建了一个对象并返回一个指向该对象的指针。

                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Rajat      |
                               +--------------------------+
    
  • 然后您将地址复制到另一个指向对象的指针中的对象。所以基本上现在两个指针都指向同一个对象。

                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Rajat      |
           person2-----------> |                          |
                               +--------------------------+
    
  • 现在,您使用一个指针更改了name 的值,并使用一个指针更改了值,同时更改了person1person2

person2->setName("Karan")
                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Karan      |
           person2-----------> |                          |
                               +--------------------------+

是这样吗?

不!基本上它只改变了它指向的对象。因此对于一个对象。事实上,从来没有两个对象,从来没有创建过两个对象。它是两个指针指向的同一个对象。

第二种情况

  • 您创建了一个对象和该对象(不是指向该对象的指针)并存储在变量 person1 中。

                               +--------------------------+
                               | Person Object (Person 1) |
                               |        name = Karan      |
                               |                          |
                               +--------------------------+
    
  • 现在,当你分配person2 = person1时,这里涉及到一个叫做复制构造函数的东西。

  • 它为person2 创建另一个对象,将person1 中的所有内容复制到person2

                               +--------------------------+
                               | Person Object (Person1)  |
                               |        name = Rajat      |
                               |                          |
                               +--------------------------+
    
                               +--------------------------+
                               | Person Object (Person2)  |
                               |        name = Rajat      |
                               |                          |
                               +--------------------------+
    

因此,这里我们有两个独立的对象。

  • 当您将值更改为 1 时,仅更改了 1 的值,即您真正想要更改的值。另一个独立的对象和之前一样。

                               +--------------------------+
                               | Person Object (Person1)  |
                               |        name = Rajat      |
                               |                          |
                               +--------------------------+
    
                               +--------------------------+
                               | Person Object (Person2)  |
                               |        name = Karan      |
                               |                          |
                               +--------------------------+
    

【讨论】:

  • C++ 给你这个选择的事实是它的优势之一,也是它比我们可以提到的其他语言更复杂的原因。
  • 确实@john :) ^-^
【解决方案2】:

在第一种情况下,您有指向Person 的指针,它实际上指向同一个动态分配的对象。两个指针,但没有两个单独的对象。因此,更改名称会影响两者。

在第二个中,您执行 copy initialization 并在这里创建了两个不同的对象。

Person person2 = person1;

因此,你在设置它们之后会有不同的名称。

【讨论】:

    【解决方案3】:

    在第一个 sn-p 中,您有两个指针指向两个相同的对象,这很危险,因此在使用两个指针中的任何一个进行更改时,您会更改同一个对象。请注意,您只创建了一个对象。

    Person *person2 = person1;
    

    上一行创建了一个新指针,指向指针person1所指向的同一个对象

    在第二个 sn-p 中,您创建了 person2 对象,该对象与 person1 不同,但 name 数据成员的值相同(因为您使用了复制 ctor),然后您已更改person2name 的值,因此有两个不同的名称。

    Person person2 = person1;
    

    上一行使用复制角色创建了一个新对象,因此数据成员具有相同的值。

    【讨论】:

      猜你喜欢
      • 2013-09-24
      • 2016-03-18
      • 2020-10-12
      • 1970-01-01
      • 2017-06-25
      • 2021-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多