【问题标题】:Copy Constructor (Deep Copy) c++复制构造函数(深拷贝)c++
【发布时间】:2015-02-27 02:19:18
【问题描述】:

我正在处理一项任务,该任务要求在构造带指针的类时编写 Big 3 的函数实现。我似乎在使用复制构造函数时遇到了问题。我认为我做的其他 2 正确。

class RealBox
{
private:
  float* m_reals;                     // Array of Real Numbers
  int m_boxsize;                      // number of Real Numbers in this box


public:
  // Purpose: Constructs an Real-Box
        // Preconditions:
        //     's' is greater than 0;
  // Postconditions:
  //     m_reals points to a dynamically allocated array of size 's'
  //     all elements of m_reals[] are initiallized to 'a'.

  RealBox(int s, float a);



  /*
   * --------- Big 3 Member Functions -----------
   */

  // Purpose: Destructor
  // Postconditions: m_reals[] deallocated
  ~RealBox();

  // Purpose: Operator=, performs a deep copy of 'rhs' into 'this' RealBox
  // Parameters: rhs, RealBox to be copied
  // Returns: *this
  // Postconditions: *this == rhs
  const RealBox& operator=(const RealBox& rhs);

  // Purpose: Copy Constructor
  // Parameters: rhs - RealBox to be copied
  // Postconditions:  *this == rhs
  RealBox(const RealBox& rhs);


  /*
   * ----- Simple Accessor Operations -----
   */

  // Purpose: Sets a value in the RealBox
  // Parameters: 'i' location to set
  //             'x' value to store
  // PreConditions: 'i' is between the boundaries of the RealBox
  // Postconditions:  element 'i' in the RealBox is set to 'x'
        void set( int i, float x);


  /*
   * ----- Complex Accessor Operations -----
   */

  // Purpose: prints the RealBox
  friend std::ostream& operator<< (std::ostream& out,
                                   const RealBox& box);
}; // RealBox

#include "realbox.h"
#include <iostream>
using namespace std;

RealBox::RealBox(int s, float a)
{
 m_reals = new float[s];
 for (int i=0; i < s; i++)
 {
  m_reals[i] = a;
 }
}

RealBox::~RealBox()
{
 delete [] m_reals;
 m_reals = NULL;
}
const RealBox& RealBox::operator =(const RealBox& rhs)
{
 if(this != &rhs)
   *this = rhs;
 return(*this);
}

RealBox::RealBox(const RealBox& rhs)
{
 m_reals = new float[m_boxsize];
 *this = rhs.m_reals;
}


void RealBox::set(int i, float x)
{
 m_reals[i] = x;
}

std::ostream& operator<< (std::ostream& out, const RealBox& box)
{
 out <<"[ ";
 for (int i = 0; i < box.m_boxsize; i++)
 {
  out << box.m_reals[i] << ", ";
 }
 out <<"]"<< endl;
 return(out);
}

当我尝试编译时,我收到了错误:

realbox.cpp:在复制构造函数“RealBox::RealBox(const RealBox&)”中: realbox.cpp:33:8: error: no match for ‘operator=’(操作数类型是 ‘RealBox’ 和 ‘float* const’)

*this = rhs.m_reals; ^ realbox.cpp:33:8: 注意:候选人是:

realbox.cpp:23:16: 注意:const RealBox& RealBox::operator=(const RealBox&) const RealBox& RealBox::operator =(const RealBox& rhs) ^ realbox.cpp:23:16: 注意:没有已知的参数 1 从‘float* const’到‘const RealBox&’的转换

我认为我的 operator = 过载也有问题,但我不确定到底出了什么问题。在我开始尝试修复之前,它没有给我那个错误。它试图说我正在比较两种不同的数据类型,但我不确定这是怎么发生的。

【问题讨论】:

  • 这些代码 sn-ps 显然不是可运行的 HTML/JavaScript。实际上,在 2015 年,你应该遵循 的规则,而不是三的规则。给自己一个可爱的std::vector 并退出所有这些手动内存管理。

标签: c++ constructor deep-copy


【解决方案1】:

这一行:

*this = rhs.m_reals;

尝试将float* 分配给RealBox 对象。这两种类型不兼容。

第二,你在构造对象的时候没有初始化m_boxsize

你想做的是这样的:

RealBox::RealBox(const RealBox& rhs) 
{
  m_boxsize = rhs.boxsize;
  m_reals = new float[m_boxsize];
  for (int i = 0; i < m_boxsize; ++i )
     m_reals[i] = rhs.m_reals[i];
}

这可以缩短为:

RealBox::RealBox(const RealBox& rhs) : m_boxsize(rhs.m_boxsize), 
                                        m_reals(new float[rhs.m_boxsize])
{  
   std::copy(rhs.m_boxsize, rhs.m_boxsize + m_boxsize, m_reals);
}

另外,你的其他构造函数需要初始化m_boxsize变量:

RealBox::RealBox(int s, float a) : m_boxsize(s)
{
   m_reals = new float[s];
   for (int i=0; i < s; i++)
       m_reals[i] = a;
}

这也可以缩短为:

RealBox::RealBox(int s, float a) : m_boxsize(s), m_reals(new float[s])
{
   std::fill( m_reals, m_reals + s, a);
}

std::fillstd::copy&lt;algorithm&gt; 标头中定义。


一旦你解决了这个问题,赋值运算符就非常简单了:

#include <algorithm>
//...
RealBox& RealBox::operator =(RealBox rhs)
{
    std::swap(rhs.m_reals, m_reals);
    std::swap(rhs.m_boxsize, m_boxsize);
    return *this;
}

使用复制/交换习语使这一切成为可能。尽可能简单。

What is the copy-and-swap idiom?

【讨论】:

    【解决方案2】:

    对不起,简短的回答...

    首先添加一个成员来保存costructor内部的表大小

    RealBox::RealBox(int s, float a)
    {
     m_reals = new float[s];
     for (int i=0; i < s; i++)
     {
      m_reals[i] = a;
     }
     m_realCount = s;
    }
    

    然后替换:

    RealBox::RealBox(const RealBox& rhs)
    {
     m_reals = new float[m_boxsize];
     *this = rhs.m_reals; // << this is a big mistake
    }
    

    作者:

    RealBox::RealBox(const RealBox& rhs)
    {
     this->m_reals = new float[rhs.m_realCount];
     memcpy(this->m_reals,rhs.m_reals,rhs.m_realCount*sizeof(float));
     this->m_realCount = rhs.m_realCount;
    }
    

    您可能需要包含 stdlib.h

    【讨论】:

    • 您的复制构造函数错误。您没有为 this-&gt;m_reals 分配内存,并且您没有复制正确的数量(memcpy 需要字节计数,而不是元素计数)
    猜你喜欢
    • 1970-01-01
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-16
    • 1970-01-01
    • 2012-11-11
    相关资源
    最近更新 更多