[英]Why converting a pointer into a reference doesn't work in my accessor (getter)?
I have recently learned how to convert a pointer into a reference using this tip . 最近,我学习了如何使用此技巧将指针转换为引用。 But when I do this in an accessor, it seems to create an undefined behavior, and I can't understand why.
但是,当我在访问器中执行此操作时,似乎会创建未定义的行为,并且我不明白为什么。
Why I want to do this 为什么我要这样做
I have a class WalkerOwner
which owns an instance of the class Walker
. 我有一个
class WalkerOwner
,它拥有class Walker
的实例。 This instance of Walker
is needed elsewhere in the code, so I have provided an accessor (getter) to the class WalkerOwner
, which gives a reference. 该
Walker
实例在代码的其他地方也需要,因此我为WalkerOwner
类提供了一个访问器(获取器),该类提供了引用。
class WalkerOwner
{
public:
...
Walker& getWalker() {return m_ownedWalker;} ;
private:
Walker m_ownedWalker;
};
Later on, I realized that WalkerOwner
should actually internally manage a pointer to the walker for some reason. 后来,我意识到
WalkerOwner
实际上应该出于某种原因在内部管理指向Walker的指针。 As I don't want to refactor the rest of my code, changing every reference to a pointer, I have tried to convert the pointer into a reference in the getter. 由于我不想重构代码的其余部分,而是将每个引用更改为指针,因此我尝试将指针转换为getter中的引用。
Code which shows the problem 显示问题的代码
#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;
}
When I run this code, I get the following output: 运行此代码时,得到以下输出:
I have walked 5 meters!
我走了5米! How good I am!
我有多好!
I have walked -858993460 meters!
我走了-858993460米! How good I am!
我有多好!
An interesting thing is that a breakpoint shows that jack is in the expected state just before calling the function "swank()". 一个有趣的事情是,断点表明在调用函数“ swank()”之前,jack处于预期状态。 (Humm... Maybe swanking has made him lose his mind!)
(哼哼……也许是抽烟使他失去了理智!)
Anyway, I would be very glad if someone could explain to me this behavior, and could tell if it is possible to make a safe accessor that performs this conversion. 无论如何,如果有人可以向我解释此行为,并告诉是否可以进行此转换的安全访问器,我将感到非常高兴。
By writing return Walker(*m_ownedWalker);
通过编写
return Walker(*m_ownedWalker);
, you're not "converting" from *m_ownedWalker
to a full Walker
: you're creating a new Walker
using the current one as a source. ,您并没有将
*m_ownedWalker
转换为完整的Walker
:您正在使用当前的Walker
作为源来创建新的 Walker
。
Simply return *m_ownedWalker;
只需
return *m_ownedWalker;
As @user2079303 points out: because you're returning a new Walker
, and then not saving it anywhere (saving a reference is not the same as saving the actual value), it gets destroyed immediately. 正如@ user2079303指出的那样:因为您要返回一个新的
Walker
,然后又不在任何地方保存它(保存引用与保存实际值并不相同),它会立即被销毁。 And then you derefence the (now-dead, uninitialised-anyway) copy - no wonder garbage was printed out! 然后您取消引用(无论如何,现在都是已死的,未初始化的)副本-难怪会打印出垃圾!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.