簡體   English   中英

為什么將指針轉換為引用在我的訪問器(getter)中不起作用?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM