簡體   English   中英

使用復制構造函數修復淺拷貝

[英]fixing shallow copy with a copy constructor

我定義了一個復制構造函數來避免數據成員 n 的淺拷貝,但它不起作用,當我更改 v1 時,v2 仍在更改,我做錯了什么?

#include<iostream>
using namespace std;
class Vector
{
  public:
  int *n;

  Vector();
  Vector(const Vector& vector );

};
Vector::Vector()
{
  cout<<"Constructor called"<<endl;
}
Vector::Vector(const Vector& vector )
{
  n=new int;
  n=vector.n;
  cout<<"Copy constructor called"<<endl;
}



int main()
{
  Vector v1;
  int x=5;
  v1.n=&x;
  Vector v2=v1;

  cout <<"Vector v1 has n value: "<<*v1.n<<endl;
  cout <<"Vector v2 has n value: "<<*v2.n<<endl;
  *v1.n=499; 
  cout <<"Vector v1 has n value: "<<*v1.n<<endl;
  cout <<"Vector v2 has n value: "<<*v2.n<<endl;

  return 0;
}


問題是您的復制構造函數實現錯誤。 嘗試修復淺拷貝問題,但您的代碼包含再次引入相同問題的語句。

在這條線上:

n=new int;

您正確分配了一個新的int ,這很好。

但在這一行:

n=vector.n;

您正在丟棄剛剛分配的int ,而是將n n的相同int 這又是淺拷貝問題。

要正確解決此問題,您需要將另一個向量的n成員的值復制到新分配的n成員中,例如:

n = new int;
*n = *(vector.n);

或者:

n = new int( *(vector.n) );

話雖如此,要完全遵守“3 規則” ,您還需要為 free n添加一個析構函數(這意味着您不能使v1指向main()中的本地int變量),以及添加一個復制賦值運算符來復制n(類似於復制構造函數)。 在 C++11 中,您還可以通過添加移動構造函數和移動賦值運算符來選擇遵守“5 規則”。

試試這個:

#include <iostream>
#include <utility>
//using namespace std; // <-- bad practice!

class Vector
{
private:
  int *m_n;

public:
  Vector(int x = 0);
  Vector(const Vector &src);
  Vector(Vector &&src);
  ~Vector();

  Vector& operator=(const Vector &src);
  Vector& operator=(Vector &&src);
  // alternatively, both operators can be merged into one:
  // Vector& operator=(Vector src);

  // you should not give outside code directly access to the int* itself,
  // that would promote bad practices, and potentially crash your class's
  // internal code if outside code assigns a bad pointer.
  //
  // these accessors provide safer use of the *value* that the int* points
  // at, let the class itself be the sole handler of the int* itself ...
  int n() const;
  void n(int x);
};

Vector::Vector(int x)
  : m_n( new int(x) )
{
  std::cout << "Converting Constructor called" << std::endl;
}

Vector::Vector(const Vector &src)
  : m_n( new int(src.n()) )
{
  std::cout << "Copy constructor called" << std::endl;
}

Vector::Vector(Vector &&src)
  : m_n( src.m_n )
{
  src.m_n = nullptr;
  std::cout << "Move constructor called" << std::endl;
}

Vector::~Vector()
{
  delete m_n;
  std::cout << "Destructor called" << std::endl;
}

Vector& Vector::operator=(const Vector &src)
{
  if (&src != this) {
    *m_n = src.n();
  }
  std::cout << "Copy assignment called" << std::endl;
  return *this;
}

Vector& Vector::operator=(Vector &&src)
{
  Vector tmp(std::move(src));
  std::swap(m_n, tmp.m_n);
  std::cout << "Move assignment called" << std::endl;
  return *this;
}

/* alternatively:
Vector& Vector::operator=(Vector src)
{
  std::swap(m_n, src.m_n);
  std::cout << "Assignment called" << std::endl;
  return *this;
}
*/

int Vector::n() const
{
  return *m_n;
}

void Vector::n(int x)
{
  *m_n = x;
}


int main()
{
  Vector v1(5);
  Vector v2 = v1;

  std::cout << "Vector v1 has n value: "<< v1.n() << std::endl;
  std::cout << "Vector v2 has n value: "<< v2.n() << std::endl;

  v1.n(499);

  std::cout << "Vector v1 has n value: " << v1.n() << std::endl;
  std::cout << "Vector v2 has n value: "<< v2.n() << std::endl;

  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM