当前位置: 首页 > 编程日记 > 正文

【C++】拷贝,赋值与构造

拷贝,赋值与构造

文章目录

    • 拷贝,赋值与构造
      • 1. 拷贝构造函数/合成拷贝构造函数(copy constructor)
      • 2. 拷贝赋值运算符
      • 3. 析构函数

1. 拷贝构造函数/合成拷贝构造函数(copy constructor)

1.1 定义:复制构造函数是一个构造函数,它的第一个参数是对类类型的引用,任何附加参数都有默认值。

1.2 如下情况使用:

  • case 1:使用 = 定义变量
  • case 2: 将对象作为参数传递给非引用类型的参数
  • case 3: 从具有非引用返回类型的函数返回一个对象
  • case 4: 括号初始化数组中的元素或聚合类的成员
  • case 5:一些类类型还为它们分配的对象使用复制初始化。

1.3 形如下:

拷贝构造函数的第一个参数必须是类的引用类型,拷贝构造函数在几种情况下P265会被隐式引用,因此,通常不应该不应该是 explicit 的

class Foo{public: Foo();Foo(const Foo& obj);//拷贝构造函数
}

1.4 解释Sales_data::Sales_data(Sales_data rhs);

拷贝构造函数用来初始化非引用类类型参数,这一特性解释为什么拷贝构造函数自己的参数必须是引用类型。

如上,如果这样声明,调用将永远不会成功调用复制构造函数,Sales_data rhs 是实际的参数(实参),因此,我们需要使用复制构造函数来复制参数,但是要复制参数,我们又将需要调用复制构造函数,如此无限期地陷入死循环,依此类推。

1.5 即使我们自己定义拷贝构造函数,编译器也会为我们合成一个拷贝构造函数(synthesized copy constructor),对某些类来说,合成拷贝构造函数是用来阻止我们拷贝该类类型的对象。一般情况,合成拷贝构造函数会将其参数成员逐个拷贝到正在创建的对象中,编译器从给定对象中依次将每个非静态成员拷贝到正在创建的对象中。

1.6 ** What happens when we copy a StrBlob? What about StrBlobPtrs? **

// added a public member function to StrBlob and StrBlobPrts
long count() {return data.use_count(); // and wptr.use_count();
}// test codes in main()
StrBlob str({ "hello", "world" });
std::cout << "before: " << str.count() << std::endl; // 1
StrBlob str_cp(str);
std::cout << "after: " << str.count() << std::endl;  // 2ConstStrBlobPtr p(str);
std::cout << "before: " << p.count() << std::endl; // 2
ConstStrBlobPtr p_cp(p);
std::cout << "after: " << p.count() << std::endl; // 2

当我们复制一个 StrBlob 时,shared_ptr 成员的 use_count 加一。

当我们复制一个 StrBlobPrts 时,weak_ptr 成员的 use_count 不会改变。(因为计数属于 shared_ptr)

1.7 假设 Point 是具有公共复制构造函数的类类型,请确定此程序片段中复制构造函数的每次使用:

Point global;
Point foo_bar(Point arg) // 1
{Point local = arg, *heap = new Point(global); // 2, 3*heap = local;Point pa[ 4 ] = { local, *heap }; // 4, 5return *heap; // 6
}

1.8 ex13_05_h,给定以下类,编写一个复制所有成员的复制构造函数新增构造函数应该动态分配一个新字符串并复制 ps 指向的对象,而不是复制 ps 本身。

class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }
private:std::string *ps;int i;
};
#include <string>class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) { }
private:std::string *ps;int i;
};

2. 拷贝赋值运算符

2.1 重载运算符(overloaded operator),本质上是一个函数,由 operator + 自定义运算符组成

2.2 拷贝赋值运算符是什么?(复制赋值运算符是名为 operator= 的函数,它采用与类相同类型的参数。)

什么时候用?(发生赋值行为时候)

合成拷贝赋值运算符完成什么工作?(合成的复制赋值运算符,它会将使用该成员类型的复制赋值运算符的右侧对象的每个非静态成员分配给左侧对象的相应成员。)

什么时候会生成合成拷贝赋值运算符?(当类没有定义自己的类时,它会被合成。)

2.3 例子如下

class Foo{public: Foo();Foo& operator=(const Foo& obj);//赋值运算符
}

2.4 合成拷贝赋值运算符用来禁止该对象的赋值P450。

3. 析构函数

3.1 析构函数是什么?合成析构函数完成什么任务?什么时候生成合成析构函数?

析构函数是一个成员函数,类名前面加一个波浪号(~)。
类似拷贝构造函数和拷贝赋值操作运算符一样,对于某些类,合成析构函数被用来阻止该类型的对象被销毁。
编译器为任何没有定义自己的析构函数的类定义合成析构函数。

析构函数:在一个构造函数中**,成员的初始化是在一个函数体执行之前**完成,且按照他们在类中出现的顺序进行初始化。在析构函数中,首先执行函数体,然后销毁成员,成员的销毁顺序按照初始化的逆序进行

在对象最后依次使用后,析构函数的函数体可以执行类设计者希望执行的任何收尾工作,通常,析构函数释放对象在生存期分配的所有资源。

3.1.1 什么时候调用析构函数?

无论何时一个对象被销毁,都会自动调用其析构函数

  • 变量离开其作用域
  • 当一个对象被销毁时,其成员被销毁
  • 容器(stl vector等)被销毁时,其元素自动被销毁。
  • 堆与动态分配的对象,当调用delete运算符删除其对应的指针时,其元素被销毁
  • 堆与临时对象,当创建它的完整表达式结束时被销毁

3.2 当一个StrBlob对象被销毁时会发生什么? StrBlobPtr呢?

当销毁StrBlob对象时,动态对象的use_count将会减少(1)。如果没有shared_ptr指向该动态对象,则释放它
当一个StrBlobPter对象被销毁时,动态分配的对象将不会被释放。

3.3 Add a destructor to your HasPtr class from the previous exercises. ex13_11.h

#include <string>class HasPtr {
public:HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0) { }HasPtr(const HasPtr &hp) : ps(new std::string(*hp.ps)), i(hp.i) { }HasPtr& operator=(const HasPtr &hp) {std::string *new_ps = new std::string(*hp.ps);delete ps;ps = new_ps;i = hp.i;return *this;}~HasPtr() { delete ps; }      //deconstructor
private:std::string *ps;int i;
};

相关文章:

Java 内存查看与分析

2019独角兽企业重金招聘Python工程师标准>>> 1&#xff1a;gc日志输出 在jvm启动参数中加入 -XX:PrintGC -XX:PrintGCDetails -XX:PrintGCTimestamps -XX:PrintGCApplicationStopedTime&#xff0c;jvm将会按照这些参数顺序输出gc概要信息&#xff0c;详细信息&…

玩转Vuejs--核心原理

一、摘要&#xff1a; Vuejs是一款前端MVVM框架&#xff0c;利用Vuejs、webpack以及周边一系列生态工具我们可以快速的构建起一个前端应用&#xff0c;网上对于Vue的分析大都是基于各个模块&#xff0c;理解起来不够顺畅&#xff0c;本文将从整个执行过程出发&#xff0c;讲一下…

【C++】拷贝控制与资源管理

1. 拷贝控制与资源管理 管理类外资源的类必须定义拷贝控制成员。如P447中所见&#xff0c;这种类需要通过析构函数来释放对象所分配的资源。一旦一个类需要析构函数&#xff0c;那么几乎可确定它也需要一个拷贝构造函数和一个拷贝赋值函数。 明确拷贝语义&#xff1a;可以定义…

leangoo V5.4.2版上线

本次更新增加了“卡片编辑面板内显示成员、截止日期、工作量”的功能。同时我们也进行了大量的功能优化&#xff0c;以下是此次更新详情&#xff1a; 1. 新增“卡片编辑面板内显示成员、截止日期、工作量”功能 本次更新后 &#xff0c;您在卡片编辑面板内添加成员&#xff0c;…

差分边缘检测实现

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/opencv.hpp> using namespace cv; // 图像差分操作 void diffOperation(const cv::Mat srcImage, cv::Mat& edgeXImage,cv::Mat& edgeYImage) {cv::Mat…

2.1:CGPROGRAM

文章著作权归作者所有。转载请联系作者&#xff0c;并在文中注明出处&#xff0c;给出原文链接。 本系列原更新于作者的github博客&#xff0c;这里给出链接。 前言 经过前面两个章节的铺垫&#xff0c;我们对渲染以及Unity Shaderlab相关的知识已经有了大概的认识&#xff0c;…

【OpenCV】OpenCV中积分图函数与应用

OpenCV中积分图函数与应用 参考资料 opencv 查找integral&#xff0c;目前网上大部分的资料来自于opencv https://docs.opencv.org/master/d7/d1b/group__imgproc__misc.html#gadeaf38d7701d7ad371278d663c50c77dhttps://blog.csdn.net/jia20003/article/details/52710751ht…

django学习笔记【003】创建第一个带有model的app

【1】python应用程序要连接mysql有多个驱动程序可供选择&#xff1a; 1、MySQLdb 这个只支持python2.x 所以在这里就不说了&#xff1b; 2、mysqlclient 下载地址   https://pypi.python.org/pypi/mysqlclient/1.3.9 3、MySQL Connector/python 这个是mysql官方主推的mysql驱…

图像非极大值抑制 Sobel 边缘实现

bool SobelVerEdge(cv::Mat srcImage, cv::Mat& resultImage) {CV_Assert(srcImage.channels() 1);srcImage.convertTo(srcImage, CV_32FC1);// 水平方向的 Sobel 算子cv::Mat sobelx (cv::Mat_<float>(3,3) << -0.125, 0, 0.125,-0.25, 0, 0.25,-0.125, 0, …

第四次作业 (日期和jieba库的运用)

设计题1&#xff1a; 设计一个本月份日历&#xff0c;输出格式如下&#xff1a; 要求&#xff1a; 1.初始化start_day&#xff0c;end_day两个日期 from datetime import datetime start_daydatetime(2019,4,1) end_daydatetime(2019,4,30) 其它时间数据生成要用datetime或date…

【C++】LINK类型错误分析记录

LINK类型错误 情况1&#xff1a; 根据生成路径&#xff0c;查找是否成功生成静态库/动态库&#xff0c;一般在./bin文件中。 情况2&#xff1a; 是否在CMakeLists中target_link_libraries中添加链接静态库操作 情况3&#xff1a; 是都存在类模板&#xff0c;需要实例化&a…

eBay宣布发布全新的购买和销售APIs

eBay最近宣布发布两款全新的购买和销售APIs。这些APIs旨在促进eBay产品在第三方应用程序中的更好集成。eBay于10月19日在他们的博客上发表了几篇文章&#xff0c;不仅详细介绍了这些全新的购买和销售APIs提供的功能&#xff0c;而且还详细地总结了他们公司从SOAP&#xff08;简…

Sobel 边缘实现

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; // 非极大值抑制实现sobel竖直细化边缘 bool SobelVerEdge(cv::Mat srcImage, cv::…

vue下实现textarea类似密码框的功能之探索input输入框keyup,keydown,input事件的触发顺序...

项目中引入element的input框组件&#xff0c;触发事件必须要加上.native <el-input placeholder"请输入" type"textarea" v-model"valueText" keyup.native"keyUp(valueText,$event)" keydown.native"keyDown($event)" …

【C++】动态内存管理/move/以及移动构造与移动赋值运算符

文章目录1 .对象移动与右值引用 实际应用过程中遇到的问题及其解决方案c中临时变量不能作为非const的引用参数2. 动态内存管理类3. 对象移动与右值引用4. 移动构造与移动复制运算符1 .对象移动与右值引用 实际应用过程中遇到的问题及其解决方案 问题描述&#xff1a; bool Cr…

图像直接卷积 Sobel 边缘实现

bool sobelEdge(const cv::Mat& srcImage, cv::Mat& resultImage,uchar threshold) {CV_Assert(srcImage.channels() 1);// 初始化水平核因子Mat sobelx (Mat_<double>(3, 3) << 1, 0,-1, 2, 0, -2, 1, 0, -1);// 初始化垂直核因子Mat sobely (Mat_&…

JSON.parse解析特殊字符报错解决方案

2019独角兽企业重金招聘Python工程师标准>>> 具体案例&#xff1a; 页面点击”下一任务” 会去请求后台&#xff0c;这里出现的问题是有虚拟任务的时候。然后会返回一个map&#xff0c;也就是如下图中回调函数中的data。 当该map里存有以下字符的时候&#xff1a; \…

MySQL数据库字符集和整理

MySQL数据库字符集和整理(2009-11-20 22:23:37)mysql数据库 it 其实这个表在MySQL数据库中通过phpMyAdmin就能看到&#xff0c;icech只是把表格整理了一下方便大家使用&#xff0c;如果要更换数据库的字符集&#xff0c;心里有数。其中有三种utf8_general_ci、utf8_unicode_ci…

【SLAM后端】—— ceres优化相机位姿求解

求解结果如下&#xff1a; mat 初始化&#xff0c;eigenvalue初始化 Mat K ( Mat_<double> ( 3,3 ) << 520.9, 0, 325.1, 0, 521.0, 249.7, 0, 0, 1 );Eigen::Matrix<float,3,1> vd_3d;v_3d << 3, 2, 1;求解目标函数结构体构造与实例 struct CurveFi…

SPOJ 1811 LCS [后缀自动机]

题意&#xff1a; 求两个串的最大连续子串 一个串建SAM&#xff0c;另一个串在上面跑 注意如果走了Suffix Link&#xff0c;sum需要更新为t[u].val1 Suffix Link有点像失配吧&#xff0c;当前状态s走不了了就到Suffix Link指向的状态fa上去&#xff0c;fa是s的后缀所以是可行的…

图像卷积下非极大值抑制 Sobel 的实现

bool sobelOptaEdge(const cv::Mat& srcImage, cv::Mat& resultImage, int flag) {CV_Assert(srcImage.channels() 1);// 初始化sobel水平核因子cv::Mat sobelX (cv::Mat_<double>(3, 3) << 1, 0, -1,2, 0, -2, 1, 0, -1);// 初始化sebel垂直核因子cv::…

was unable to refresh its cache! status = Cannot execute request on any known server

出现这种错误是因为: Eureka服务注册中心也会将自己作为客户端来尝试注册它自己&#xff0c;所以我们需要禁用它的客户端注册行为。 在 yml中设置 eureka.client.register-with-eurekafalse eureka.client.fetch-registryfalse 但在服务端是要这是为false的&#xff0c;在客…

【C++】浅析析构函数(基类中)为什么要写成虚基类?

为什么有了虚析构函数&#xff0c;就能先调用子类的析构函数&#xff1f; class A {virtual ~A(){} };class B : A {virtual ~B(){} };A *p new B(); delete p; 唯一差别是&#xff0c;每个析构函数结束时会自动&#xff08;隐含地&#xff09;调上父类的析构函数&#xff0…

Roberts 边缘检测

#include <opencv2/opencv.hpp> // roberts算子实现 cv::Mat roberts(cv::Mat srcImage) {cv::Mat dstImage srcImage.clone();int nRows dstImage.rows;int nCols dstImage.cols;for (int i 0; i < nRows - 1; i){for (int j 0; j < nCols - 1; j){// 根据公…

vector、map删除当前记录

map<string, string> sMap; map<string, string>::iterator iter; for(iter sMap.begin();iter ! sMap.end();/* iter */) {sMap.erase(iter); }注意下列错误表达&#xff1a;1. for(iter sMap.begin();iter ! sMap.end(); iter ) {sMap.erase(iter); } 错误原因…

1-2 postman工具简介

postman提供了一个多窗口和多选项卡页面用于发送和接受请求&#xff0c;postman努力保持整洁和灵活&#xff0c;提供更多的空间&#xff0c;满足用户的需要。他很简单&#xff0c;能满足大部分接口的测试&#xff0c;性价比特别高。如图所示&#xff1a; 1.侧边栏 postman的侧边…

【C++】重载运算符(一)

1.1 重载运算符特点 重载运算符本质上是一次函数调用 除了operator() 运算符调用外&#xff0c;其他重载运算符不能含有默认参数。 当重载的运算符是成员函数时&#xff0c;this绑定到左侧运算对象。成员运算符函数&#xff08;显式&#xff09;的参数数量比运算对象少一个。…

javaScript的调试(二)

2019独角兽企业重金招聘Python工程师标准>>> 一、Firebug Firebug是Firefox浏览器的调试工具&#xff0c;只要我们在Firefox中安装了Firebug应用&#xff0c;就可以按F12或右击鼠标开启调试 那么我们就先来看一下如何在Firefox中安装了Firebug应用&#xff0c;一图剩…

Prewitt 边缘检测

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include "opencv2/imgproc/imgproc.hpp" #include <iostream> // prewitt算子实现 cv::Mat prewitts(cv::Mat img, bool verFlag false) {img.convertTo(img, CV_32FC…

[swift 进阶]读书笔记-第十一章:互用性 C11P1 实践:封装 CommonMark

第十一章&#xff1a;互用性 Interoperability 前言&#xff1a; swift 的最大优点就是与C 或者 OC 混编的时候稳的一匹 本章主要讲了swift和C之间的一些知识点。 11.1 实践:封装 CommonMark Hands-On: Wrapping CommonMark 这一小节更像是一个教程。教你如何封装C语言中的Comm…