【问题标题】:Copy Constructor and Overloaded Assignment?复制构造函数和重载赋值?
【发布时间】:2015-04-27 06:09:55
【问题描述】:

谁能在下面提到的代码中向我解释赋值运算符。我有

问题 1:为什么赋值运算符返回引用对象 [我知道这是用于类似 c1 = c2 = c3 的东西,但这是如何工作的]

Quest 2:我创建了动态指针tempName,但我没有释放内存,所以有内存泄漏。我该如何解决。或者有的话给我举个例子。

任务3:我已经在name中分配了tempName,所以name指向tempName如果我在return之前删除tempName,那么会发生什么。

Contact& operator=( const Contact& rhs ) {
  char* tempName = new char[ strlen( rhs. name ) + 1] ;
  delete[ ] name;
  name = tempName;
  strcpy( name, rhs. name ) ;
  age = rhs. age;
  return *this;
}

【问题讨论】:

    标签: c++ operator-overloading copy-constructor assignment-operator


    【解决方案1】:

    第一季度。

    当您返回对对象的引用时,您可以将其放在赋值的左侧以分配另一个值。所以,我认为有两个原因。

    (1) 避免不必要的复制。

    (2) C++中赋值的默认行为,你可以这样做

    a = (b = c)
    

    (a = b) = c
    

    即使返回值,第一种形式也可以。 但是对于第二个,您必须返回对该值的引用才能具有与普通 C++ 赋值相同的行为。

     

    第二季度。

    是的,它有内存泄漏。除非,你删除了析构函数中的name

     

    第三季度。

    nametempName 指向同一个地址。因此,删除 tempName 将删除 name 指向的内容。不要这样做。

     

    此外,使用 C++,为什么不使用 std::string 而不是 C 风格的字符串,而让 std::string 来管理它的内存。


    当然,您可以不遵守 C++ 的方式,对操作员有自己的行为。但不推荐。

    【讨论】:

    • 另外请注意,使用std::string而不是手动管理char *name;不能超卖。有了它,这个自定义赋值运算符和看不见的 copy-ctor 很可能都不是必需的,因为两者的编译器默认值可能就足够了。
    • @WhozCraig:确实如此,这样可以避免编写copy-ctr时不必要的复杂性。
    【解决方案2】:
    1. 为了避免不必要的复制。即使您返回一个值,链接也会起作用,因此并非绝对必要。返回引用主要是模仿本地类型的赋值,其中编译器返回左值而不是右值。甚至编译器生成的赋值运算符也会返回一个引用。

    2. 你在析构函数中删除了内存。

    3. 如果删除后返回,调用者将无法使用。

    【讨论】:

      【解决方案3】:

      问题一:

      在 C++ 中(就像在 C 中一样),赋值返回一个值。事实上a = b = c 很简单:a = (b = c) 因为b = c 返回 b 的新值。

      这就是为什么要避免破坏语言语义,赋值操作必须在赋值后返回对对象的引用。

      问题2:

      必须在失去对指针的访问权之前释放内存。一种简单的方法是将原始指针封装在对象中,并在(封装对象的)析构函数中进行删除。这就是为什么std::unique_ptr 的原因。但是在这个用例中,tempname 已经影响到对象的name 属性。只需删除 Contact 析构函数中的 name

      问题3:

      this->name 似乎是一个原始指针,恰好指向新分配的tempname。如果在返回之前删除tempnamethis->name 将指向已释放的内存 => 所谓的悬空指针。

      【讨论】:

        【解决方案4】:

        1:为什么赋值运算符返回引用对象

        链式赋值是一种语法,您可以一次将值分配给多个持有者,例如a = b = c。你可以这样理解:b=c; a=b;,因为它从右到左执行堆栈。链接可以通过按值返回和按引用返回来实现。 现在回到你的问题“为什么引用?”。参考用于优化。当您按值返回时,会创建该值的副本并将其发送回调用代码。 请考虑以下代码以更好地理解:

        class A { int _a; public: void setA(int a){ _a = a; } A() :_a(0){} A operator=(const A&);// here we are returning by value A& operator=(const A&);// here we are returning by reference. //Both support chaining but using reference avoids unnecessary copy };


        2: 我创建了动态指针 tempName 但我没有释放内存,所以有内存泄漏。我该如何解决。或者给我举个例子,如果你有

        您不必使用 tempName 分配内存,而是可以使用 'name' 本身。参考下面代码sn-p:

        delete[ ] name;

        char* name = new char[ strlen( rhs. name ) + 1];
        

        3:我在name中分配了tempName,所以name指向tempName如果我在return之前删除tempName,那么会发生什么。

        因为在您的代码中(这并不理想),名称和 tempName 指向相同的内存位置。删除tempName 将导致name 的堆损坏,这意味着当您尝试访问name 时程序将中断。


        我希望这会有所帮助。评论任何进一步的澄清。

        【讨论】:

        • 在访问 rhs.name 之前删除 name 会在自分配时调用未定义的行为。
        猜你喜欢
        • 2014-10-12
        • 2013-10-23
        • 2012-02-12
        • 2016-09-13
        • 1970-01-01
        • 1970-01-01
        • 2015-01-04
        • 2011-07-19
        • 1970-01-01
        相关资源
        最近更新 更多