[英]Why converting a pointer into a reference doesn't work in my accessor (getter)?
最近,我學習了如何使用此技巧將指針轉換為引用。 但是,當我在訪問器中執行此操作時,似乎會創建未定義的行為,並且我不明白為什么。
為什么我要這樣做
我有一個class WalkerOwner
,它擁有class Walker
的實例。 該Walker
實例在代碼的其他地方也需要,因此我為WalkerOwner
類提供了一個訪問器(獲取器),該類提供了引用。
class WalkerOwner
{
public:
...
Walker& getWalker() {return m_ownedWalker;} ;
private:
Walker m_ownedWalker;
};
后來,我意識到WalkerOwner
實際上應該出於某種原因在內部管理指向Walker的指針。 由於我不想重構代碼的其余部分,而是將每個引用更改為指針,因此我嘗試將指針轉換為getter中的引用。
顯示問題的代碼
#include <iostream>
#include <string>
using std::string;
class Walker
{
public:
Walker() : m_travelledDistance(5) {};
~Walker(){};
void swank() { std::cout << "I have walked " << distanceAsString() << "! How good I am!" << std::endl; };
private:
// Calling this function makes the result even more impressive
string distanceAsString() { return std::to_string(m_travelledDistance) + " meters" ; };
int m_travelledDistance;
};
class WalkerOwner
{
public:
WalkerOwner() {m_ownedWalker = new Walker; } ;
~WalkerOwner() { delete m_ownedWalker;};
// I know I should throw an exception if the pointer is not valid.
Walker& getWalker() {return Walker(*m_ownedWalker);} ; //conversion from pointer into reference
private:
Walker* m_ownedWalker;
};
int main(int argc, char *argv[])
{
// -------
// Case 1
// If "main" owns John the walker, everything seems fine.
// -------
Walker* ptrToJohn = new Walker ;
Walker& john = Walker(*ptrToJohn); //conversion from pointer into reference
john.swank();
delete ptrToJohn ;
// -------
// Case 2
// If someone else owns Jack the walker, a disaster occurs.
// -------
WalkerOwner walkerOwner ;
Walker& jack = walkerOwner.getWalker() ;
// (When I put a breakpoint here, my Integrated Devlopment
// Environnment says that walker.m_travelledDistance = 5)
jack.swank();
std::cin.get(); // Press enter to close
return EXIT_SUCCESS;
}
運行此代碼時,得到以下輸出:
我走了5米! 我有多好!
我走了-858993460米! 我有多好!
一個有趣的事情是,斷點表明在調用函數“ swank()”之前,jack處於預期狀態。 (哼哼……也許是抽煙使他失去了理智!)
無論如何,如果有人可以向我解釋此行為,並告訴是否可以進行此轉換的安全訪問器,我將感到非常高興。
通過編寫return Walker(*m_ownedWalker);
,您並沒有將*m_ownedWalker
轉換為完整的Walker
:您正在使用當前的Walker
作為源來創建新的 Walker
。
只需return *m_ownedWalker;
正如@ user2079303指出的那樣:因為您要返回一個新的Walker
,然后又不在任何地方保存它(保存引用與保存實際值並不相同),它會立即被銷毀。 然后您取消引用(無論如何,現在都是已死的,未初始化的)副本-難怪會打印出垃圾!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.