指针工作然后看起来没有理由

时间:2015-01-07 22:16:09

标签: c++ pointers

为什么在分配指针后我可以访问对象中保存的数据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.

3 个答案:

答案 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