【问题标题】:Weird behavior of default copy constructor in C++C++ 中默认复制构造函数的奇怪行为
【发布时间】:2018-01-06 19:52:32
【问题描述】:

在学习 C++ 中的隐式复制构造函数时,我遇到了一个奇怪的行为。这是关于这堆代码的:

#include <iostream>

class Person
{
public:
    char* name;
    int age;

    Person( const char* the_name, int the_age )
    {
        name = new char[strlen( the_name ) + 1];
        strcpy( name, the_name );
        age = the_age;
    }

    ~Person()
    {
        delete[] name;
    }
};

int main(){
    Person p1( "Tom", 22 );

    Person p2( p1 );
    p2.name = "Bill";

    // the output is: "Tom"
    std::cout << p1.name << std::endl;

    std::cin.get();
}

默认情况下,复制一个对象意味着复制其成员,因此在使用默认复制构造函数创建p2 对象时,它应该只复制一个指针name,而不是它指向的字符数组。因此更改对象p2name 成员应该更改对象p1name 成员。因此p1.name 应该是"Bill" 而不是"Tom"

我的推理有什么问题?为什么要打印"Tom"

【问题讨论】:

  • 它正在打印Tom,因为这是p1.name 所指向的。将p2.name 指向其他地方并不会改变这一点。不过请阅读rule of zero。它将防止许多此类错误。
  • 是的,子对象是指针 name,而不是 name 指向的任何东西......如果我在我的财产上放置一个指向附近湖的标志,这并不意味着我拥有这个湖。最多我拥有这个标志。
  • 你不会改变p1.name指向的内存。您的 C++ 书是否没有说明为什么使用 strcpy 复制 C 字符串?
  • 您似乎将指针与引用混淆了。 p2.name 不是对p1.name 的引用,它只是一个最初指向与p1.name 相同地址的指针。重新分配一个不会影响另一个。
  • 拿一张纸。在两个角写上“Tom”和“Bill”。在其他角落用 p1.name 和 p2.name 绘制圆圈。在这些圆圈附近绘制指向“汤姆”的小箭头。这些是您的指针,箭头是它们的值。现在擦除 p2 圆圈中的箭头并绘制新的箭头,指向“Bill”。您重新分配了 p2 指针。现在,角落里写着什么,p1箭头指向的是什么?

标签: c++ object constructor copy implicit


【解决方案1】:

默认情况下,复制一个对象意味着复制它的成员

是的。

因此,在使用默认复制构造函数创建p2 对象时,它应该只复制一个指针name,而不是它指向的字符数组。

正确。

因此更改对象p2的名称成员应该更改对象p1的名称成员。

不。是的,p2.namep1.name 指向同一个内存位置,但这并不意味着更改 p1.name 的指针 value 会更改 p2.name 的值。如果那是ints,如果更改p1.name 没有影响p2.name,你会感到惊讶吗?因为这里是一样的。你有两个不同的变量,改变一个变量的值不会改变另一个变量的值。

int a = 0;
int b = 1;

int* ptrA = &a;
int *ptrA2 = &a;

*ptrA = 1; // now a == 1
*ptrA2 = 4; // now a == 4

ptrA2 = &b;

*ptrA2 = 10; // now b == 10
*ptrA = 3; // now a == 3, a != 10  

【讨论】:

  • 我认为在我的例子中只有一个变量(内存中的字符)和两个指针指向它。
  • @jaayy 不是。你只有两个变量,两个指针,指向某个内存位置。但是它们是不同的变量,所以改变一个不会改变另一个,当然,除非你正在访问两个指针指向的内存,因为它们指向同一个地方。
  • 我不明白。我有两个变量在同一个内存位置?你说我有两个变量,两个指针,指向同一个内存位置。那么第一个指针指向第一个变量,第二个指针指向第二个变量,同时指针指向相同的内存位置?这对我来说是不一致的。
  • @jaayy 不,我不是那个意思。这两个指针当然有不同的内存位置,但它们指向同一个位置。第一个指向内存位置,第二个也指向同一个。
  • 我已经知道我的问题是什么。我认为像p2.name = "Bill"; 这样的写行我正在更改p2.name 指向的内存,但我正在为字符串"Bill" 分配新内存。如果我会做p2.name[1] = 'b',程序的输出将是'Tbm'。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2015-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-14
  • 1970-01-01
  • 2015-04-05
相关资源
最近更新 更多