C++中的赋值操作符重载和拷贝构造函数
1,关于赋值的疑问:
1,什么时候需要重载赋值操作符?
2,编译器是否提供默认的赋值操作符?
2,关于赋值的疑问:
1,编译器为每个类默认重载了赋值操作符;
1,意味着同类型的类对象可以相互赋值;
2,默认的赋值操作符仅完成浅拷贝;
3,当需要进行深拷贝时必须重载赋值操作符;
1,和拷贝构造函数相同;
4,赋值操作符与拷贝构造函数有相同的存在意义;
3,默认赋值操作符重载编程实验:
1,main.cpp 文件:
#include <iostream>
#include <string> using namespace std; class Test
{
int* m_pointer;
public:
Test()
{
m_pointer = NULL;
}
Test(int i)
{
m_pointer = new int(i);
}
Test(const Test& obj)
{
m_pointer = new int(*obj.m_pointer);
}
Test& operator = (const Test& obj)
{
if( this != &obj ) // 避免自赋值;
{
delete m_pointer;
m_pointer = new int(*obj.m_pointer);
} return *this;
}
void print()
{
cout << "m_pointer = " << hex << m_pointer << endl;
}
~Test()
{
delete m_pointer;
}
}; int main()
{
Test t1 = ;
Test t2; t2 = t1; // 默认赋值操作符的浅拷贝使得两个对象内部指针指向同一片空间; int i = ; // C 语言中允许这样,所以 C++ 中也必须允许;
i = i; t2 = t2; // C++ 中也要允许自赋值,但是没有意义; t1.print();
t2.print(); return ;
}
2,输出结果:
m_pointer = 0x9387008
m_pointer = 0x9387018
3,赋值操作符重载注意事项:
1,赋值操作符返回值一定是引用,为了连续赋值;
2,参数类型一定是 const Type&;
3,不能自赋值;
4,返回当前对象;
4,关于赋值的疑问:

1,如果要进行深拷贝,拷贝构造函数和赋值操作符的实现都要自定义;
5,一般性原则:
1,重载赋值操作符,必然要实现深拷贝;
1,实现深拷贝和自定义赋值操作符及拷贝构造函数是充要条件;
6,数组类的优化编程实验:
1,IntArray.h 文件:
#ifndef _INTARRAY_H_
#define _INTARRAY_H_ class IntArray
{
private:
int m_length;
int* m_pointer; IntArray(int len);
IntArray(const IntArray& obj);
bool construct();
public:
static IntArray* NewInstance(int length);
int length();
bool get(int index, int& value);
bool set(int index ,int value);
int& operator [] (int index);
IntArray& operator = (const IntArray& obj);
IntArray& self();
~IntArray();
};
2,首先写出赋值操作符注意事项模板:
IntArray& IntArray::operator = (cosnt IntArray& obj)
{
if( this != &obj )
{ } return *this;
}
3,函数实现:
IntArray& IntArray::operator = (const IntArray& obj)
{
if( this != &obj )
{
int* pointer = new int[obj.m_length]; if( pointer )
{
/* 复制参数对象中的元素 */
for(int i=; i<obj.m_length; i++)
{
pointer[i] = obj.m_pointer[i];
} /* 深拷贝 */
m_length = obj.m_length;
delete[] m_pointer;
m_pointer = pointer;
}
} return *this;
}
4,main.cpp 文件:
#include <iostream>
#include <string>
#include "IntArray.h" using namespace std; int main()
{
IntArray* a = IntArray::NewInstance();
IntArray* b = IntArray::NewInstance(); if( a && b )
{
IntArray& array = a->self();
IntArray& brray = b->self(); cout << "array.length() = " << array.length() << endl;
cout << "brray.length() = " << brray.length() << endl; array = brray; cout << "array.length() = " << array.length() << endl;
cout << "brray.length() = " << brray.length() << endl;
} delete a;
delete b; return ;
}
5,输出结果:
array.length() =
brray.length() =
array.length() =
brray.length() =
6,使用二阶构造后,拷贝构造函数是私有的,拷贝构造函数就没有作用了,不允许拷贝构造,但是应该重载赋值操作符重载;
7,编译器默认提供函数:

1,虽然类中什么都没写,但是编译器会放四个函数实现进去;
8,下面的代码输出什么?为什么?
1,代码示例:
string s = "";
const char* p = s.c_str(); // 返回字符指针,代表 C 语言中的字符串; cout << p << endl; s.append("abced"); cout << p << endl;
9,字符串问题 1 编程实验:
1,main.cpp 文件:
#include <iostream>
#include <string> using namespace std; int main()
{
string s = "";
const char* p = s.c_str(); // 只有这一行用了 C 方式; cout << p << endl; s.append("abced"); // p 成为了野指针 cout << p << endl; return ;
}
2,这段代码混合了 C 和 C++ 的方式,出了意想不到的错误;
10,关于 string 的疑问 1:

1,string 对象内部维护了一个指向数据的 char* 指针,这个指针可能在程序 运行的过程中发生改变,我们尽量不要操作这个指针;
2,执行 s.append() 函数后,char* 指针指向了新的堆空间 0xFF445566,而将旧的堆空间 0xFF112233 释放,此时 p 指针成了野指针;
3,学习 C++,并且用的是标准库中的内容,所以现在采用的编程思想就应该是 C++ 编程思想,不要混合使用 C 和 C++ 思想;
11,下面的程序输出什么?为什么?
1,代码示例:
const char* p = ""; // p 可以用字符串对象代替;
string s = ""; // 混合了,该注意了; s.reserve(); // 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=; i<; i++)
{
s[i] = p[i];
} if( !s.empty() )
{
cout << s << endl;
}
2,没有输出;
12,字符串问题 2 编程实验:
1,main.cpp 文件:
#include <iostream>
#include <string> using namespace std; int main()
{
const char* p = "";
string s = ""; s.reserve(); // 不要使用 C 语言中的方式操作 C++ 中的字符串
for(int i=; i<; i++)
{
s[i] = p[i];
} if( !s.empty() ) // 打印不出;
{
cout << s << endl;
} cout << s << endl; // 打印不出; for(int i=; i<; i++) // 可以打印;
{
cout << s[i] << endl;
} return ;
}
2,更改程序为:
#include <iostream>
#include <string> using namespace std; int main()
{
const string p = "";
string s = ""; s = p; cout << s << endl; return ;
}
3,C++ 工程中,尽量避免指针使用,字符串类出现就是为了替代字符指针;
13,关于 string 的疑问 2:

14,小结:
1,在需要进行深拷贝的时候必须重载赋值操作符;
1,也要重新定义拷贝构造函数;
2,赋值操作符和拷贝构造函数有同等重要的意义;
3,string 类通过一个数据空间保存字符串数据;
4,string 类通过一个成员变量保存当前字符串的长度;
5,C++ 开发时尽量避开 C 语言中惯用的编程思想;
1,字符串类得到的是字符串对象,直接用成员函数操作这个对象就可以,不需要用 C 语言中的 for 循环之类的;
C++中的赋值操作符重载和拷贝构造函数的更多相关文章
- 析构函数-复制构造函数-赋值操作符重载-默认构造函数<代码解析>
通过下面primer中的一道习题,可以更深刻的了解,析构函数,复制构造函数,赋值操作符重载,默认构造函数的使用. 但是我的结果与primer习题解答里面的并不相同,可能是编译器不同的原因导致. // ...
- C#中如何利用操作符重载和转换操作符
操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...
- C#中如何利用操作符重载和转换操作符 (转载)
操作符重载 有的编程语言允许一个类型定义操作符应该如何操作类型的实例,比如string类型和int类型都重载了(==)和(+)等操作符,当编译器发现两个int类型的实例使用+操作符的时候,编译器会生成 ...
- C++中的数组操作符重载
1,本文讲述数组操作符重载,上篇博文的字符串类 string 确实强大,但 string 类 对象还具备 C 方式字符串的灵活性吗?还能直接访问单个字符吗? 1,C 方式字符串灵活性是指能够通过数组 ...
- C++与java中的赋值操作符
#include <iostream> using namespace std; class BankAccount{ private: double balance; public: B ...
- python基础(5):深入理解 python 中的赋值、引用、拷贝、作用域
http://my.oschina.net/leejun2005/blog/145911 http://www.cnblogs.com/lulipro/p/5060163.html http://ww ...
- [c++基础]3/5原则--拷贝构造函数+拷贝赋值操作符
/* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> #include &qu ...
- C++ 拷贝构造函数和赋值构造函数
转自:http://blog.chinaunix.net/uid-28662931-id-3496326.html 一.拷贝构造函数 int main(int argc, char * argv[]) ...
- C++构造函数详解(复制构造函数 也是 拷贝构造函数)
构造函数是干什么的 该类对象被创建时,编译系统对象分配内存空间,并自动调用该构造函数,由构造函数完成成员的初始化工作,故:构造函数的作用:初始化对象的数据成员. 构造函数的种类 1 class Com ...
随机推荐
- Struts 2 配置Action详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 实现了Action处理类之后,就可以在struts.xml中配置该Action,从而让Struts 2框架知道哪个Act ...
- 【leetcode】1209. Remove All Adjacent Duplicates in String II
题目如下: Given a string s, a k duplicate removal consists of choosing k adjacent and equal letters from ...
- mysql分组排序加序号
参照https://www.cnblogs.com/CharlieLau/p/6737243.html 一.需求 新加一个Sort 字段,初始值为1,按照parentID分组添加sort值. 根据原数 ...
- vue学习-day03(动画,组件)
目录: 1.品牌列表-从数据库获取列表 2.品牌列表-完成添加功能 3.品牌列表-完成删除功能 4.品牌列表-全局配置数据接口的根域名 5.品牌列表-全局配置emulateJS ...
- Elastic-Job快速入门
1 Elastic-Job快速入门1.1 环境搭建1.1.1.版本要求JDK要求1.7及以上版本Maven要求3.0.4及以上版本zookeeper要求采用3.4.6及以上版本1.1.2.Zookee ...
- 01-scrapy框架
1.Scrapy图例: Scrapy Engine(引擎): 负责Spider.ItemPipeline.Downloader.Scheduler中间的通讯,信号.数据传递等. Scheduler(调 ...
- FP AUTO节点ZPP002M执行卡住解决
正常情况下,不到一分钟即可执行完ZPP002M节点 异常情况下,超过十分钟都没有响应 再等待只会影响FP的执行时间,影响后续的节点,解决办法是将正在执行的JOB STOP掉 再到服务器上将该节点重新执 ...
- Spotlight_on_windows 安装和监控
一.下载 1.下载并安装Spotlight_on_windows 2.填写注册码 Authorization Key:295713336449229168750 Site Message:Bergel ...
- sqli-labs(9)
基于时间的GET单引号盲注 0x01爱之初试探 在我们注入了SQL代码之后,存在以下两种情况: 如果注入的SQL代码不影响后台[数据库]的正常功能执行,那么Web应用的页面显示正确(原始页面). 如果 ...
- vue 路由懒加载 resolve vue-router配置
使用方法 component:resolve => require(['@/pages/About'],resolve) //"@"相当于".." 懒加载 ...