赋值运算符和拷贝构造函数C ++ [英] assignment operator vs. copy constructor C++

查看:131
本文介绍了赋值运算符和拷贝构造函数C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码来测试我对C ++中基本指针的理解:

  // Integer.cpp 
#includeInteger.h
Integer :: Integer()
{
value = new int;
* value = 0;
}

Integer :: Integer(int intVal)
{
value = new int;
* value = intVal;
}

Integer ::〜Integer()
{
delete value;
}

Integer :: Integer(const Integer& rhInt)
{
value = new int;
* value = * rhInt.value;
}

int Integer :: getInteger()const
{
return * value;
}

void Integer :: setInteger(int newInteger)
{
* value = newInteger;
}

整数& Integer :: operator =(const Integer& rhInt)
{
* value = * rhInt.value;
return * this;
}

// IntegerTest.cpp
#include< iostream>
#include< cstdlib>
#includeInteger.h

using namespace std;

void displayInteger(char * str,Integer intObj)
{
cout< str<< is<< intObj.getInteger()<< endl;
}

int main(int argc,char * argv [])
{
Integer intVal1;
Integer intVal2(10);

displayInteger(intVal1,intVal1);
displayInteger(intVal2,intVal2);

intVal1 = intVal2;

DisplayInteger(intVal1,intVal1);

return EXIT_SUCCESS;
}

此代码的工作原理与预期的一样,打印输出:

  intVal1为0 

intVal2为10

intVal1为10



然而,如果我删除复制构造函数,它会打印出如下:

  intVal1是0 

intVal2是10

intVal1是6705152
pre>

我不明白为什么会出现这种情况。我的理解是,当分配给不存在的对象时,使用复制构造函数。这里 intVal1 确实存在,所以为什么不赋值运算符?

解决方案

在分配期间不使用复制构造函数。在传递参数到 displayInteger 函数时,使用了case中的复制构造函数。



您的版本的复制构造函数执行深度数据拥有的复制通过类(就像你的赋值运算符)。所以,一切正常工作与您的版本的复制构造函数。



如果你删除自己的复制构造函数,编译器会为你隐式生成一个。编译器生成的复制构造函数将执行对象的 shallow 复制。这将违反三条规则,并销毁您课程的功能,这正是你在实验中观察到的。基本上,第一次调用 displayInteger 会损坏您的 intVal1 对象,第二次调用 displayInteger 损害您的 intVal2 对象。之后,你的对象都被打破,这就是为什么第三个 displayInteger 调用显示垃圾。



displayInteger



的声明

  void displayInteger(char * str,const Integer& intObj)

即使没有明确的拷贝构造函数,代码也会工作。但是,忽略三条规则不是一个好主意任何情况。以这种方式实现的类必须服从三项规则或必须使其不可复制。


I have the following code to test out my understanding of basic pointers in C++:

// Integer.cpp
#include "Integer.h"
Integer::Integer()
{
  value = new int;
  *value = 0;
}

Integer::Integer( int intVal )
{
  value = new int;
  *value = intVal;
} 

Integer::~Integer()
{
  delete value;
}

Integer::Integer(const Integer &rhInt)
{
  value = new int;
  *value = *rhInt.value;
}

int Integer::getInteger() const
{
  return *value;
}

void Integer::setInteger( int newInteger )
{
  *value = newInteger;
}

Integer& Integer::operator=( const Integer& rhInt )
{   
  *value = *rhInt.value;
  return *this;
}

// IntegerTest.cpp
#include <iostream>
#include <cstdlib>
#include "Integer.h"

using namespace std;

void displayInteger( char* str, Integer intObj )
{
  cout << str << " is " << intObj.getInteger() << endl;
}

int main( int argc, char* argv[] )
{
 Integer intVal1;
 Integer intVal2(10);

 displayInteger( "intVal1", intVal1 );
 displayInteger( "intVal2", intVal2 );

 intVal1 = intVal2;

 displayInteger( "intVal1", intVal1 );

 return EXIT_SUCCESS;
}

This code works exactly as expected as is, it prints out:

intVal1 is 0

intVal2 is 10

intVal1 is 10

However if I remove the copy constructor it prints out something like:

intVal1 is 0

intVal2 is 10

intVal1 is 6705152

I don't understand why this is the case. My understanding is that the copy constructor is used when the assignment is to an object that doesn't exist. Here intVal1 does exist, so why isn't the assignment operator called?

解决方案

The copy constructor is not used during assignment. Copy constructor in your case is used when passing arguments to displayInteger function. The second parameter is passed by value, meaning that it is initailized by copy contructor.

Your version of copy constructor performs deep copying of data owned by the class (just like your assignment operator does). So, everything works correctly with your version of copy constructor.

If you remove your own copy constructor, the compiler will generate one for you implicitly. The compiler-generated copy constructor will perform shallow copying of the object. This will violate the "Rule of Three" and destroy the functionality of your class, which is exactly what you observe in your experiment. Basically, the first call to displayInteger damages your intVal1 object and the second call to displayInteger damages your intVal2 object. After that both of your objects are broken, which is why the third displayInteger call displays garbage.

If you change the declaration of displayInteger to

void displayInteger( char* str, const Integer &intObj )

your code will "work" even without an explicit copy constructor. But it is not a good idea to ignore the "Rule of Three" in any case. A class implemented in this way either has to obey the "Rule of Three" or has to be made non-copyable.

这篇关于赋值运算符和拷贝构造函数C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆