为什么在分配指针后我可以访问对象中保存的数据WHILE我在分配函数的范围内,但是一旦我尝试通过相同的指针访问相同的值但是不能功能
指针是成员函数,在函数内分配。在函数内,这工作正常。但是,当从函数内部调用时,我调用另一个使用类范围的函数,指针行为异常,呈现垃圾数据。为什么呢?
CODE:
#include <iostream>
class Object{
public:
Object( ) { std::cout << "Object constructor called." << std::endl; }
Object( const Object &in ) { i = in.i; std::cout << "Object copy constructor called." << std::endl; }
~Object( ) { std::cout << "Object destructor called." << std::endl; }
int i;
};
class ObjectManager{
public:
Object * retObject(){
Object *myObject = new Object;
myObject->i=55;
return myObject;
}
};
class LogicManager{
public:
LogicManager(){
myObjectManager = new ObjectManager;
}
~LogicManager(){
delete myObjectManager;
}
Object * retObject(){
return myObjectManager->retObject();
}
private:
ObjectManager *myObjectManager;
};
class Viewer{
public:
~Viewer( ) { if( myObject ) { delete myObject; } }
void ptrinObject( LogicManager * inLogic ){
myObject = inLogic->retObject();
std::cout << "Got path size of " << myObject->i << std::endl; //correct
std::cout << "Got path size of " << retObjectVal( ) << std::endl; //0?!?!?!?
}
int retObjectVal( ) { myObject->i; }
private:
Object *myObject;
};
int main(){
LogicManager myManager;
Viewer myViewer;
//myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
return 0;
}
输出:
Object constructor called.
Got path size of 55
Got path size of 861280848
Object destructor called.
答案 0 :(得分:7)
问题是:
int retObjectVal( ) { myObject->i; }
该函数中没有return
语句。你只有一个没有副作用的表达。结果,我们遇到§6.6.3/ 2:
离开函数末尾相当于没有值的返回;这导致未定义 价值回归函数中的行为。
它返回的是未定义的行为,因此它最终会返回一些垃圾。做到这一点:
int retObjectVal() { return myObject->i; }
这是一个容易犯的错误,这就是为什么你应该总是尝试使用尽可能高的警告设置进行编译。例如,在没有标志的gcc上,我没有得到任何警告。但是-Wall
,我得到了:
警告:声明无效[-Wunused-value]
警告:函数返回非void [-Wreturn-type]
时没有return语句
答案 1 :(得分:1)
首先,如果您只是
,则不会初始化Viewer::myObject
void something() {
Viewer v;
}
您可能最终会尝试删除无效指针。
myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
这两个函数都创建了一个新的Object
,但都没有检查是否已经分配了一个(内存泄漏)。然后,他们会立即忽略创建的新对象,而是分配另一个由Object
分配的新ObjectManager
(更多内存泄漏)。
最后,Viewer::retObjectVal
实际上并没有明确return
一个值,因此您在函数结束时收到&#34;垃圾&#34;。
我建议你查看你的编译器警告,因为任何明智的编译器都会警告你我所提到的第一和第三个问题。
答案 2 :(得分:0)
在Viewer
课程中,您缺少return
声明:
int retObjectVal( ) { return myObject->i; }
应该有用。
你所拥有的是一种方法,其中一些分支在没有返回值的情况下脱落。这导致未定义的行为。你只是评估“myObject-&gt; i;”作为陈述。
您应该解决的另一个问题是您的Object指针不属于任何人,并且不会被删除。也就是说,您正在删除ObjectManager
,但它根本没有delete
基础对象本身。您应该在那里找出所有权模型,让某人跟踪这些指针,并在适当的时候delete
。