最近用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++函数返回值发生的对象复制的更多相关文章

  1. C++函数返回值为类对象但未调用复制构造函数

    参考资料:https://blog.csdn.net/sxhelijian/article/details/50977946 不要迷信书本,要学会自己调试程序.

  2. Python3_函数参数传递、可变与不可变对象、变量作用域、函数返回值

    参数传递: 在 python 中,类型属于对象,变量是没有类型的:(变量都仅仅是一个对象的引用,没有类型之分)a=[1,2,3] a="Runoob" 以上代码中,[1,2,3] ...

  3. 获得函数返回值类型、参数tuple、成员函数指针中的对象类型

    //function_traits.h,获得函数返回值类型.参数tuple.成员函数指针中的对象类型 //参考https://github.com/qicosmos/cosmos/blob/maste ...

  4. C++ const修饰函数、函数参数、函数返回值

    const修饰函数 在类中将成员函数修饰为const表明在该函数体内,不能修改对象的数据成员而且不能调用非const函数.为什么不能调用非const函数?因为非const函数可能修改数据成员,cons ...

  5. 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数

    [源码下载] 速战速决 (3) - PHP: 函数基础, 函数参数, 函数返回值, 可变函数, 匿名函数, 闭包函数, 回调函数 作者:webabcd 介绍速战速决 之 PHP 函数基础 函数参数 函 ...

  6. 关于QT中evaluateJavaScript()函数返回值的处理问题

    关于QT中evaluateJavaScript()函数返回值的处理问题 - 寒风问雪的专栏 - 博客频道 - CSDN.NET 关于QT中evaluateJavaScript()函数返回值的处理问题 ...

  7. C++函数返回值(02)

    对象作为返回值 编译器会将函数栈中的返回值数据拷贝到返回栈中 指针作为返回值 函数的返回值可以是存储某种类型数据的内存地址,称这种函数为指针函数.它们的一般定义形式如下:  类型标识符 *函数名(参数 ...

  8. Python第七天 函数 函数参数 函数里的变量 函数返回值 多类型传值 函数递归调用 匿名函数 内置函数

    Python第七天   函数  函数参数   函数里的变量   函数返回值  多类型传值     函数递归调用   匿名函数   内置函数 目录 Pycharm使用技巧(转载) Python第一天   ...

  9. 转 C++函数返回值,你必须注意的问题

    归根结底,C++所面临的问题要求它提供各种各样的机制以保证性能,也许,这辈子也见不到C++能安全有效的自己进行内存垃圾回收..... 老程序猿都会提醒菜鸟,注意函数的返回值,因为,很可能,你的函数返回 ...

随机推荐

  1. MLlib--SVD算法

    转载请标明出处http://www.cnblogs.com/haozhengfei/p/4db529fa9f4c042673c6dc8218251f6c.html SVD算法 1.1什么是SVD?   ...

  2. Redis 数据结构与内存管理策略(下)

    Redis 数据结构与内存管理策略(下) 标签: Redis Redis数据结构 Redis内存管理策略 Redis数据类型 Redis类型映射 Redis 数据类型特点与使用场景 String.Li ...

  3. 【开发技术】Get请求和Post请求区别

    a.Get请求是通过URL请求来提交表单数据的:Post是通过HTTP中的POST机制将表单中的数据提交到Action所定制的程序,如果有附件需要用Post方式. b.Get适用于传输数据量小于1K数 ...

  4. 使用VSCode和VS2017编译调试STM32程序

    近两年,微软越来越拥抱开源支持跨平台,win10搭载Linux子系统,开源VSCode作为跨平台编辑器,VS2017官方支持了Linux和嵌入式开发功能. ST也是,近两年开发的软件工具基本都是跨平台 ...

  5. 04 整合IDEA+Maven+SSM框架的高并发的商品秒杀项目之高并发优化

    Github:https://github.com/nnngu 项目源代码:https://github.com/nnngu/nguSeckill 关于并发 并发性上不去是因为当多个线程同时访问一行数 ...

  6. 转发:python 装饰器--这篇文章讲的通俗易懂

    转 http://www.cnblogs.com/wupeiqi/articles/4980620.html 1.必备 #### 第一波 #### def foo():     print 'foo' ...

  7. laravel5.5 when()的用法

    当你在使用where语句有前提条件时,比如某值为1的时候才执行where子句,否则不执行,这个时候,laravel5.5新出了一个简便方法when($arg,fun1[,fun2]). 具体用法如下: ...

  8. linkin大话面向对象--封装和隐藏

    软件开发追求的境界:高内聚,低耦合 高内聚:尽可能把模块的内部数据,功能实现细节隐藏在模块内部独立完成,不允许外部直接干预 低耦合:仅暴露少量的方法给外部使用 到底为什么要对一个雷或者对象实现良好的封 ...

  9. 布衣之路(一):VMware虚拟机+CentOS系统安装

    前言:布衣博主乃苦逼的Java程序猿一枚,虽然工作中不会涉及系统运维,但是开发的项目总还是要部署到服务器做一些负载均衡.系统兼容性测试.系统集成等等骚操作,而这些测试性的操作不可能直接SSH远程运维的 ...

  10. Python笔记001-----简介及常用的库

    1.Python是一种解释性语言,大部分代码要比编译型语言(如C++,java等)运行要慢点多.2.对于高并发,多线程的应用程序而言,Python并不是理想语言,python有全局解释器锁(Globa ...