[英]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.