【问题标题】:Returning a pointer from a method从方法返回指针
【发布时间】:2013-06-21 15:22:25
【问题描述】:

我的程序中有一个特定的类,我用它来绘制各种形状并为形状添加事件。

vector<XQuad*> _inputMappedShape;
void addRegularShape(Container inputPoints, Container outputPoints){
XQuad quad;
setInputPoints(quad, somePoints);
setInputPoints(quad, somePoints);
setArrowHandles(quad, somePoints);
_inputMappedShape[currentIndex++] = &quad;
}

XQuad* getMappedShape(int index){
return _inputMappedShape[index];
}

void setInputPoints(XQuad& quad, Point* somePoints);
void setOutputPoints(XQuad& quad, Point* somePoint);
void setArrowHandles(XQuad& quad, Point* somePoint);

请注意,在上面的代码中(在方法addRegularshape 中),在将quad 添加到vector 集合之前,我通过引用其他方法传递了quad

在我的主程序中,我尝试使用 getMappedShape 方法检索形状,该方法将返回一个指向四边形的指针以用于我的目的。
XQuad* returnedShape = getMappedShape(0)

我检查了addRegularShape方法中分配的quad的内存地址和指针返回的地址(来自方法getMappedShape)和内存地址是一样的。
但是,不知何故,当从getMappedShape 返回时,我的XQuad 类中的数据不正确(即不是在其他三个成员函数中的 XQuad 引用对象中修改的数据),而是有一些垃圾值。我找不到发生这种情况的原因,并且怀疑内存损坏或其他原因,我将addRegularShape中的引用对象更改为指针,如下所示。
XQuad* quad = new XQuad();

在此之后,程序开始返回正确的值,但我仍然有点怀疑它为什么会发生?添加 XQuad 对象不是将地址添加到集合的正确方法吗?或者这里是否存在一些范围问题,即当方法超出范围时,对象被销毁并且我从集合中实际返回的内容现在变成了垃圾值?

【问题讨论】:

    标签: c++ pointers reference


    【解决方案1】:
    _inputMappedShape[currentIndex++] = &quad;
    

    表示您将四边形的地址分配给 _inputMappedShape。所以你会在你的完整程序中得到这个地址.. 但是在函数 addRegularShape(...) 的末尾,与四边形对象关联的数据将被销毁,因为它的范围将结束.. 并且 _inputMappedShape 将保留四边形的地址没有数据。

    【讨论】:

    • 当对应的指针指向一个被破坏的对象时,一个引用将指向一个被破坏的对象。因此,原则上您可以返回对对象的引用,前提是您可以返回指向该对象的指针。在实践中,如果调用者必须删除该对象,您将希望返回指向该对象的指针(或者更好的是智能指针)。
    【解决方案2】:

    你得到垃圾值是因为我们将本地对象 XQuad 的地址传递给成员变量 _inputMappedShape[currentIndex++] = &quad

    当你创建一个局部变量时要记住这一点,那么分配给该局部变量的内存总是在堆栈上。因此,一旦您退出该函数,堆栈就会展开,现在您的 _inputMappedShape[currentIndex++] 将指向某个实际上不存在的位置。

    但是如果你在一个方法中使用 new 操作符创建一个变量,那么分配给它的内存将不再是在堆栈上而是在堆上。在这种情况下,从该函数返回时堆栈展开不会对变量 _inputMappedShape[currentIndex++] 产生影响。

    【讨论】:

      【解决方案3】:

      您正在返回本地对象的地址(将在函数调用结束时销毁),因此您最终会出现未定义的行为。

      【讨论】:

      • 是否存在我实际上可以从方法返回引用的情况?我试图使用引用来避免显式使用指针。例如:一个类,它可能有构造函数初始化的私有变量。类的 getter 方法返回对私有变量的引用,例如 int&amp; getTopLeftCornerX( return _pTopLeftX); 其中 _pTopLeftX 是类的私有变量,并使用类构造函数初始化。
      • 对 OP 的一个很好但也有点痛苦的提示:提高编译器的警告级别。尝试编写完全不产生警告的代码。例如,gcc 会警告您返回对局部变量的引用。
      • @user1240679:有很多案例。例如。 std::vector::at() 确实如此。 Çclass 方法一般可以返回对类数据成员的引用;他们确实比一个电话更长寿。但是您的案例是您不应该的典型示例。 getter 应该是const,最好返回一个普通的int
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      • 2018-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2012-04-18
      相关资源
      最近更新 更多