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