我有class A一個main()功能:
class A {
public: int num;
public: A* parent;
A(){};
A::A (const A &s)
{
this->num = s.num;
this->parent = s.parent;
}
public : vector <A> foo(A a)
{
A a1;
a1.num = a.num;
a1.parent = &a;
vector <A> list;
list.reserve(1);
list.push_back(a1);
A temp = list.front();
cout << temp.parent->num << endl;
return list;
}
};
int main()
{
A a;
a.num =2;
vector <A> list = a.foo(a);
A temp = list.front();
cout << temp.parent->num << endl;
return 0;
}
問題是cout內部foo()按預期列印 2,但cout內部main()列印的是一個巨大的數字。
我認為問題與記憶體重定位有關,正如我從多個來源讀取的那樣,所以我嘗試使用reserve()但它沒有用。
誰能幫我解決這個問題?
uj5u.com熱心網友回復:
在foo()中,您按值a傳遞引數。這意味著傳遞給的物件被復制到引數中。引數本身是的區域變數。因此,被設定為指向區域變數。Amain()foo()aafoo()a1.parent
然后復制list.push_back(a1);,復制指標。然后在保存 to 的結果時制作另一個副本。a1parentlist.front()temp
因此,取消參考temp.parent內部的指標foo()是完全有效的,因為a它parent指向的指標在記憶體中仍然有效。
然而,一旦foo()退出,a就會被銷毀,留下復制的parent指標懸空,指向現在無效的記憶體。因此,在 中main(),取消參考parent指標是未定義的行為,因為該指標不再指向原始a物件。
如果您為A物件的構造和銷毀添加一些日志記錄,您可以很容易地自己看到這一點,例如:
class A {
public:
int num = 0;
A* parent = nullptr;
A(){ cout << "A created: " << this << endl; }
A(const A &s) : num(s.num), parent(s.parent)
{
cout << "A copied: " << &s << " -> " << this << endl;
}
~A(){ cout << "A destroyed: " << this << endl; }
...
};
在線演示
你會看到這樣的記錄:
A created: 0x7ffe5e735250 // 'a' in main() is created
A copied: 0x7ffe5e735250 -> 0x7ffe5e735260 // 'a' in foo() is passed in by main()
A created: 0x7ffe5e7351e0 // 'a1' in foo() is created
A copied: 0x7ffe5e7351e0 -> 0x5592f50b2e80 // 'a1' is copied into `list` in foo()
A copied: 0x5592f50b2e80 -> 0x7ffe5e7351f0 // list.front() is copied into 'temp' in foo()
(foo) temp.parent: 0x7ffe5e735260, num: 2 // parent is pointing at 'a' in foo()
// foo() exits, 'list' is transferred to main()
A destroyed: 0x7ffe5e7351f0 // 'temp' in foo() is destroyed
A destroyed: 0x7ffe5e7351e0 // 'a1' in foo() is destroyed
A destroyed: 0x7ffe5e735260 // 'a' in foo() is destroyed !!!!!
A copied: 0x5592f50b2e80 -> 0x7ffe5e735260 // main() reuses freed memory for 'temp' in main() !!!!!
(main) temp.parent: 0x7ffe5e735260, num: 2 // parent is pointing at the wrong A object !!!!!
// main exits
A destroyed: 0x7ffe5e735260 // 'temp' in main() is destroyed
A destroyed: 0x5592f50b2e80 // `list` in main() is destroyed
A destroyed: 0x7ffe5e735250 // 'a' in main() is destroyed
要解決此問題,請更改foo()為通過參考A獲取物件(并將兩個變數也更改為參考):tempA&
vector<A> foo(A &a)
這樣,在 中,只要傳入的本地物件保持有效main(),回傳的指標將保持有效。parentafoo()
在線演示
現在,您會看到類似這樣的記錄:
A created: 0x7ffd7319e8b0 // 'a' in main() is created
// 'a' in foo() is passed in by main()
A created: 0x7ffd7319e850 // 'a1' in `foo() is created
A copied: 0x7ffd7319e850 -> 0x556ccff0fe80 // 'a1' is copied into 'list' in foo()
(foo) temp.parent: 0x7ffd7319e8b0, num: 2 // parent is pointing at 'a' in main()
// foo() exits, 'list' is transferred to main()
A destroyed: 0x7ffd7319e850 // 'a1' in foo() is destroyed
(main) temp.parent: 0x7ffd7319e8b0, num: 2 // parent is still pointing at 'a' in main()
// main() exits
A destroyed: 0x556ccff0fe80 // 'list' in main() is destroyed.
A destroyed: 0x7ffd7319e8b0 // 'a' in main() is destroyed !!!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/535452.html
標籤:C 指针记忆向量
下一篇:C 回圈檔案結構
