使用和不使用 new 关键字创建 C++ 对象

3

使用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  

Person person2 = person1 中,我原本以为 person2 指向了同一个 person1,所以预期输出结果为 'Karan Karan'。但实际情况并非如此。

有人能够解释一下 Person person2 = person1 这行代码背后的含义吗?它是否创建了一个全新的对象?


3
这是一个很好的问题,因为它突显了初学者在C++方面存在的一个非常重要的误解。Person person2 = person1;拷贝一个人的对象。绝对不是person1和person2指向同一个对象。它们是独立的(但相等的)对象。我发现许多初学者认为相反的情况很令人惊讶。我想不出任何依据这种假设的基础,除了可能是对其他语言的经验。 - john
1
如果你能清楚地理解复制引用和复制值之间的区别,那么你就能克服许多新手在理解C++时遇到的问题。 - john
@john-我也是新手C++,来自Java背景,所以有点困惑。谢谢你欣赏我的问题 :) - Karan Shetty
1
@john - 可能更公正的说,当新手之前学习了其他编程语言时,他们对C++存在一些误解。我遇到过很多人将C++作为他们的第一门编程语言学习,但他们从未有过这样的误解。一些其他的编程语言如Java、Eiffel(列表还很长)默认使用引用语义,而我从未遇到过一个对C++有“误解”的人没有在这些语言中有背景,并且只是假定C++会像他们之前学过的语言一样工作,而没有进行核实。 - Peter
@Peter 我的观点是基于我在这里看到的问题,不幸的是新手通常不会解释清楚自己的问题,但我认为这种误解比你所说的更为普遍。我并不是说新手有一个一致的理解,只是恰好是错误的(但 Karan 似乎是个例外),而是他们对复制实际上意味着什么,它是一个值还是一个引用感到困惑。通常新手对此没有一致的思考。 - john
3个回答

5

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

第一种情况

  • While using new keyword, new created an object and returned a pointer to that object.

                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Rajat      |
                               +--------------------------+
    
  • You then copied the address to the object in another pointer to object. So basically now both pointers point to the same object.

                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Rajat      |
           person2-----------> |                          |
                               +--------------------------+
    
  • Now, You then changed the value of name using one pointer and changing the value using one pointer changed both person1 and person2.

person2->setName("Karan")

                               +--------------------------+
           person1 ----------> |    Person Object         |
                               |        name = Karan      |
           person2-----------> |                          |
                               +--------------------------+

真的吗??

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

在第二种情况下

  • You created an object and that object (not a pointer to the object) and stored in variable person1.

                               +--------------------------+
                               | Person Object (Person 1) |
                               |        name = Karan      |
                               |                          |
                               +--------------------------+
    
  • Now, when you assigned person2 = person1, there is something called Copy constructor is involved here.

  • It creates another object for person2 copying everything in person1 to person2.

                               +--------------------------+
                               | Person Object (Person1)  |
                               |        name = Rajat      |
                               |                          |
                               +--------------------------+
    
                               +--------------------------+
                               | Person Object (Person2)  |
                               |        name = Rajat      |
                               |                          |
                               +--------------------------+
    
因此,这里有两个独立的对象。
  • When you changed the value for one, the value got changed for only one, for the ones you actually wanted to change. And another independent object is as it was earlier.

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

3
C++ 能够给你提供这个选择是它的优点之一,但也是为什么它比其他一些语言更加复杂的原因。 - john
是的,@john 确实如此 :) ^-^ - CodeTalker

2
在第一个片段中,你有两个指针指向同一个对象,这是很危险的。因此,当使用其中任意一个指针进行更改时,你会更改同一个对象。请注意,你只创建了一个对象。
Person *person2 = person1;

上一行代码创建了一个新的指针,指向与指针person1相同的对象。

而在第二个代码片段中,您创建了一个不同于person1person2对象,但其name数据成员的值相同(因为您使用了复制构造函数),然后更改了person2name值,因此有两个不同的名称。

Person person2 = person1;

上一行代码使用“copy actor”创建了一个新对象,因此数据成员的值相同。


2
在第一个例子中,您有指向实际上指向相同动态分配对象的 Person 的指针。两个指针但没有两个单独的对象。因此,更改名称将影响两者。
在第二个例子中,您进行了复制初始化,并在此处创建了两个完全不同的对象。
Person person2 = person1;

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接