C++函数返回值发生的对象复制
最近用QT做一个监控系统的项目,需要显示目标的运动轨迹,每次目标移动后,就在目标的轨迹中(用vector记录)添加一条新轨迹。
但是在运行中画面里一直不出现轨迹,经过调试发现是记录轨迹的函数出错了。
原程序的逻辑是:目标轨迹类是ObjectTrack,通过调用getTrack()函数获得一个vector,然后将新的坐标append到vector里。
问题出现的原因在于,getTrack()方法返回的vector不是ObjectTrack对象的成员,因为在return的时候发生了vector的复制,所以对复制后的vector添加新坐标是不会被保存的。
解决办法1:
对返回后的vector进行添加新坐标后再set回ObjectTrack对象中
这个方法会产生额外的vector副本
解决办法2:
使用引用,将getTrack()函数的返回值设置成引用,并用引用变量接收
不会产生vector的副本,比解决办法1好
解决办法3:
在ObjectTrack中添加新的函数用于追加新坐标信息
符合封装性,使用也更简单,比1、2好
对于C++对象赋值操作(还有return对象)发生的复制现象,做了以下分析:
1.当函数返回值不是引用类型是,会发生复制,且接收函数返回值的变量不能是引用类型
#include <iostream>
using namespace std; class C1
{
public:
int a;
C1(int a){
this->a = a;
}
/*复制构造函数,不修改被拷贝的对象,所以参数为const;参数是引用,
是因为如果不是引用,在传递参数的时候就会被调用复制构造函数,而这
个函数本身就是复制构造函数,会造成无穷的递归调用
*/
C1(const C1 &c){
this->a = c.a;
cout << "copy constructor called" << endl;
}
};
class C2
{
public:
C1 c1;
C2():c1(10){
}
C1 getC1(){
return c1;
}
};
int main(){
C2 c2;
C1 c1 = c2.getC1();
cout<<(int)(&c1)<<endl<<(int)(&c2.c1)<<endl;
return 0;
}
运行结果是:
copy constructor called
2686712
2686716
2.当函数返回值是引用类型,接收函数返回值的变量不是引用时,仍然发生复制
#include <iostream>
using namespace std; class C1
{
public:
int a;
C1(int a){
this->a = a;
}
/*复制构造函数,不修改被拷贝的对象,所以参数为const;参数是引用,
是因为如果不是引用,在传递参数的时候就会被调用复制构造函数,而这
个函数本身就是复制构造函数,会造成无穷的递归调用
*/
C1(const C1 &c){
this->a = c.a;
cout << "copy constructor called" << endl;
}
};
class C2
{
public:
C1 c1;
C2():c1(10){
}
C1 &getC1(){
return c1;
}
};
int main(){
C2 c2;
C1 c1 = c2.getC1();
cout<<(int)(&c1)<<endl<<(int)(&c2.c1)<<endl;
return 0;
}
运行结果是:
copy constructor called
2686712
2686716
3.函数返回值是引用类型,接收函数返回值的变量是引用类型,不会发生复制
#include <iostream>
using namespace std; class C1
{
public:
int a;
C1(int a){
this->a = a;
}
/*复制构造函数,不修改被拷贝的对象,所以参数为const;参数是引用,
是因为如果不是引用,在传递参数的时候就会被调用复制构造函数,而这
个函数本身就是复制构造函数,会造成无穷的递归调用
*/
C1(const C1 &c){
this->a = c.a;
cout << "copy constructor called" << endl;
}
};
class C2
{
public:
C1 c1;
C2():c1(10){
}
C1 &getC1(){
return c1;
}
};
int main(){
C2 c2;
C1 &c1 = c2.getC1();
cout<<(int)(&c1)<<endl<<(int)(&c2.c1)<<endl;
return 0;
}
运行结果是:
2686712
2686712
另外,数组返回值也会发生复制
String str = strs[i];
str与strs[i]也是不同的对象
C++函数返回值发生的对象复制的更多相关文章
- C++函数返回值为类对象但未调用复制构造函数
参考资料:https://blog.csdn.net/sxhelijian/article/details/50977946 不要迷信书本,要学会自己调试程序.
- Python3_函数参数传递、可变与不可变对象、变量作用域、函数返回值
参数传递: 在 python 中,类型属于对象,变量是没有类型的:(变量都仅仅是一个对象的引用,没有类型之分)a=[1,2,3] a="Runoob" 以上代码中,[1,2,3] ...
- 获得函数返回值类型、参数tuple、成员函数指针中的对象类型
//function_traits.h,获得函数返回值类型.参数tuple.成员函数指针中的对象类型 //参考https://github.com/qicosmos/cosmos/blob/maste ...
- C++ const修饰函数、函数参数、函数返回值
const修饰函数 在类中将成员函数修饰为const表明在该函数体内,不能修改对象的数据成员而且不能调用非const函数.为什么不能调用非const函数?因为非const函数可能修改数据成员,cons ...
- 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数
[源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...
- 关于QT中evaluateJavaScript()函数返回值的处理问题
关于QT中evaluateJavaScript()函数返回值的处理问题 - 寒风问雪的专栏 - 博客频道 - CSDN.NET 关于QT中evaluateJavaScript()函数返回值的处理问题 ...
- C++函数返回值(02)
对象作为返回值 编译器会将函数栈中的返回值数据拷贝到返回栈中 指针作为返回值 函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数.它们的一般定义形式如下: 类型标识符 *函数名(参数 ...
- Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数
Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数 目录 Pycharm使用技巧(转载) Python第一天 ...
- 转 C++函数返回值,你必须注意的问题
归根结底,C++所面临的问题要求它提供各种各样的机制以保证性能,也许,这辈子也见不到C++能安全有效的自己进行内存垃圾回收..... 老程序猿都会提醒菜鸟,注意函数的返回值,因为,很可能,你的函数返回 ...
随机推荐
- OBS studio最新版配置鉴权推流
这两天在看百度的LSS音视频直播服务的sdk..sdk看了一圈,基本上只能操作个流什么的,查看流列表,域名之类的.按照百度这块的描述自己去实现这个显得不是那么明智我感觉.其次就是百度LSS的教程用的O ...
- parse_url 解析 URL,返回其组成部分
parse_url - 解析 URL,返回其组成部分 array parse_url ( string $url [, int $component = -1 ] ) 本函数解析一个 URL 并返回一 ...
- windows下安装redis3.2.100单机和集群详解
下载redis 下载地址:https://github.com/MicrosoftArchive/redis/releases 我下载的是3.2.100版本的Redis-x64-3.2.100.zip ...
- 关于VC++中virtual ~的含义
我知道virtual 的虚函数定义,~CMainFrame( )是析构函数,用来释放内存.C++的继承和派生内容.所有可以被用作基类的类一般都用虚析构函数当基类对象的指针或引用调用派生类对象时,如果基 ...
- tone()函数的有趣的使用案例
tong()除了可以驱动蜂鸣器之外,还可以驱动步进电机(测试很好用) 一个引脚上产生一个特定频率的方波(%占空比).持续时间可以设定,否则波形会一直产生直到调用noTone()函数.该引脚可以连接压电 ...
- 自己写的日志框架--linkinLog4j--框架可配置+提性能
OK,上一篇博客我们已经实现了日志框架的基本的功能,但是还有一个最大的问题就是日志输出地不能重定向,然后一些输出也不可控.那现在我们来实现一个比较完整的日志框架. 设计思路如下: 1,定义一堆常量Li ...
- SQL SERVER的单用户模式以及专用管理员连接
2007-03-08 18:22:03.46 server Microsoft SQL Server 2000 - 8.00.2039 (Intel X86) May 3 2005 23:1 ...
- RESTClient
RESTClient是Mozilla Firefox一个用于测试http请求插件. 1.打开火狐扩展搜索RESTClient进行安装并重启浏览器. 2.重启后可以在Mozilla Firefox地址栏 ...
- CSS 自动隐藏文字并添加省略号
.cut { overflow:hidden; white-space:nowrap; text-overflow:ellipsis; -o-text-overflow:ellipsis; -icab ...
- Databricks缓存提升Spark性能--为什么NVMe固态硬盘能够提升10倍缓存性能(原创)
我们兴奋的宣布Databricks缓存的通用可用性,作为统一分析平台一部分的 Databricks 运行时特性,它可以将Spark工作负载的扫描速度提升10倍,并且这种改变无需任何代码修改. 1.在本 ...