繁体   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