最近用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. JavaScript八张思维导图—Date用法

    JS基本概念 JS操作符 JS基本语句 JS数组用法 Date用法 JS字符串用法 JS编程风格 JS编程实践 不知不觉做前端已经五年多了,无论是从最初的jQuery还是现在火热的Angular,Vu ...

  2. 零基础教你写python爬虫

    大家都知道python经常被用来做爬虫,用来在互联网上抓取我们需要的信息. 使用Python做爬虫,需要用到一些包: requests urllib BeautifulSoup 等等,关于python ...

  3. vue中什么样的数据可以是在视图中显示

    1. Vue中不可以添加不存在的属性,因为不存在的属性是没有getter和setter的. <div id="app"> {{msg.a}} {{msg.b}} < ...

  4. django url路由参数错误

    出现错误: TypeError get() got an unexpected keyword argument 'teacher_id 出错原因: view类中,get方法获得了一个多余的额参数,这 ...

  5. sqlserver datetime的bug

    sqlserver datetime 的毫秒的个位似乎存在bug,只有0.3.7这三个值,比如: 2018-01-20 23:59:59:999会变成2018-01-21 00:00:00.000 2 ...

  6. mysql存储过程且mybatis调用

    首先,需要执行符DELIMITER ,建议用//,即在存储过程开始前定义delimiter //,在结束后加上//,最后加上DELIMITER ; 具体原因@参考文章1写的很清楚,不再赘述. 参考文章 ...

  7. windows下使用Git Bash命令行克隆远程仓库代码

    此处使用的代码托管平台是GitLab,相比GitHub来说,它可以设置免费的私有仓库,哈哈,妈妈再也不用担心我的源码泄露了!1.切换到本地的工作目录,我的目录是: cd /d/coder/websit ...

  8. 长整形 Unix系统毫秒时间 (long类型) 转换为时间格式

    /** * 把毫秒转化成日期 * * @param dateFormat(日期格式,例如:MM/ dd/yyyy HH:mm:ss) * @param millSec(毫秒数) * @return * ...

  9. Go基础--goroutine和channel

    goroutine 在go语言中,每一个并发的执行单元叫做一个goroutine 这里说到并发,所以先解释一下并发和并行的概念: 并发:逻辑上具备同时处理多个任务的能力 并行:物理上在同一时刻执行多个 ...

  10. 【转】CentOS 6.3(x86_64)下安装Oracle 10g R2

    目 录 一.硬件要求二.软件三.系统安装注意四.安装Oracle前的系统准备工作五.安装Oracle,并进行相关设置六.升级Oracle到patchset 10.2.0.4七.使用rlwrap调用sq ...