【问题标题】:C++ with copy constructor doesn't work good带有复制构造函数的 C++ 不能正常工作
【发布时间】:2014-01-09 19:02:57
【问题描述】:

我构建了一个名为 Attribute 的对象,这个对象有完整的副本和空的构造函数。 然后我构建了另一个名为 Human 的对象,其中包含 Attribute 对象。 当我尝试以某种方式构建人类类(带有完整构造函数)时,它会自动调用 Attribute 复制构造函数,我不知道为什么。

代码如下:

char** d = new char*[3];    
    d[0] = new char[10];
    d[0] = "aa";
    d[1] = new char[10];
    d[1] = "bb";
    d[2] = new char[10];
    d[2] = "cc";

    Attribute *a = new Attribute(1.7, "blue", "white", "black", d, 3);
    Human *h = new Human("Name", *a);

当我使用调试器并到达这一行时: new Human("Name", *a);它会自动进入这个函数:

Attribute::Attribute(Attribute& copy)       
{
    Attribute(copy.height, copy.eyeColor, copy.skinColor, copy.hairColor, copy.diseases, copy.numOfDiseases);
}

只有在这个函数结束后,它才会启动 Human 完整构造函数...

【问题讨论】:

  • Rule of three 很可能...
  • 您真的需要在堆上分配HumanAttribute(即使用new 并保留一个指针)吗?我的感觉是,您使用 C++ 就好像它在 Java 中一样,这并不好。
  • 您正在泄漏内存。只要您不熟悉指针(可以说即使您熟悉),请使用 std::string 而不是 char*。
  • 您正在调用 new[],将返回值分配给一个指针,然后出于某种原因将分配的值替换为指向字符串文字的指针,从而导致内存泄漏。 d[0] = new char[10];d[0] = "aa"; \\ huh??
  • Human 的构造函数是什么样的?

标签: c++ object constructor copy


【解决方案1】:
Human *h = new Human("Name", *a);
                              ^----- Here it's passing in an Attribute by value

因此调用 Attribute 复制构造函数。

【讨论】:

    【解决方案2】:

    复制构造函数没有初始化任何东西;它只是创建和销毁一个本地临时对象。

    在 C++11 中,您可以将工作委托给另一个构造函数,就像您尝试做的那样:

    Attribute::Attribute(Attribute const & copy) :
        Attribute(copy.height, copy.eyeColor, copy.skinColor, copy.hairColor, copy.diseases, copy.numOfDiseases)
    {}
    

    从历史上看,您必须复制另一个构造函数的代码,或者将其移动到两个构造函数都调用的函数中。

    您可能还希望通过引用获取构造函数参数,这样就不需要复制它们:

    Human(std::string const & name, Attribute const & attribute);
    

    你也应该避免new,除非你真的需要它。你可能想要更多类似的东西

    Attribute a(1.7, "blue", "white", "black", d, 3);
    Human h("Name", a);
    

    当您确实需要 new 时(通常是因为您希望对象比当前范围更有效,或者有时是为了多态),请使用 RAII 管理类型,如智能指针和容器而不是原始指针,以确保对象完成后会正确删除。处理原始指针会导致内存泄漏和其他灾难。

    【讨论】:

      【解决方案3】:

      a - 是一个指针 *a - 是值

      因此,如果您的 Human 构造函数按值采用 seconds 参数

      Human::Human(char* s, Attribute a)
      

      它将复制属性并为其使用复制构造函数。 如果你不想要这种行为,你可以通过指针传递参数。

      Human::Human(char* s, Attribute *a)
      

      然后这样称呼它:

      Attribute *a = new Attribute(1.7, "blue", "white", "black", d, 3);
      Human *h = new Human("Name", a); // this works with pointer now. Pointer will be copied, but the class will remain in the same memory and wouldn't be copied anywhere.
      

      如果你想一下,行为类似于正常的值和函数:

      void f1(int a){ a++; cout << a; }
      void f2(int *a){ *a++; cout << *a; }
      
      int b = 4;
      f1(b); // It copies the value of local b to parameter a, increments local parameter a of f1 and prints it; It will print 5
      cout << b; // b will remain the same. It will print 4
      f2(&b); // It copies pointer, but both pointers &b and a point to the same variable b from this scope, and it's value is not copied 
      cout << b; // As we've worked with pointers, it was incremented in f2. It will print 5
      

      请注意,您必须处理所有指针的责任。如果您手动创建了某些内容,请不要忘记应该删除它的位置以及在哪些情况下可能存在泄漏。使用 smart_pointers 更容易做到这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-15
        • 2013-05-02
        • 2021-03-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多