最近用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]也是不同的對象
