1

我有返回对象的函数,但我很困惑我应该返回对象本身还是指向对象的指针?

这是我的功能的一个例子:

CImage CDocument::AddImage(string Name, string fileName)
{
    CImage img = CImage();
    img.Name = Name;
    img.Path = fileName;
    img.IwImage = Iw2DCreateImage(&fileName[0]);

    Images.push_back(&img);

    return img;
}

这是正确的还是我应该返回指向对象的指针:

CImage * CDocument::AddImage(string Name, string fileName)
{
    CImage * img = new CImage();
    img->Name = Name;
    img->Path = fileName;
    img->IwImage = Iw2DCreateImage(&fileName[0]);

    Images.push_back(img);

    return img;
}

虽然最后一个代码没有正确编译,因为我收到了这个错误:

error C2440: 'initializing' : cannot convert from 'CImage' to 'CImage *'

我认为这可能是一个非常简单的问题。我对 c++ 很陌生,所以请耐心等待。

4

3 回答 3

5

这段代码有多个问题,用 C++ 编码时要理解的基本区别是堆栈分配和堆分配之间的区别。当你这样做时CImage img = CImage();,对象是在 stack上创建的。该对象在函数结束时自动销毁。现在,如果您返回一个指向该对象的指针,调用者将获得一个指向无效内存位置的指针,因为该对象已经被销毁。您还将此对象的地址推送到向量中,一旦函数结束,该地址将再次无效。同样的问题也存在fileName

为了解决这个问题,您需要从堆中分配内存,以便在函数结束时不会破坏对象。new您可以使用C++在堆上分配对象。所以你的代码会变成CImage* pImage = new CImage();. 请注意,在这种情况下,您有责任使用delete. CImage*因此,您可以使用此技术更改您的函数以返回。您也可以将此指针推入向量Images中。请注意,要释放分配给对象的内存CImage,您需要遍历Images向量并显式调用delete每个指针。

更好的方法是使用智能指针,例如std::shared_ptr在这种情况下,它将delete自动为您管理调用。

于 2012-06-15T04:12:33.033 回答
3

首先修复指针部分:

CImage * img = new CImage();

修复编译器错误。

考虑实例的生命周期。一个类的实例一旦到达其作用域的末尾就会被销毁——这里是函数的右括号。

第一个示例将在函数结束时为 img 销毁(并释放内存) - 这可能会产生意外行为,具体取决于Images.push_back.

对于返回的实例,如果调用代码如下所示,很可能会创建变量的副本:

CImage outterImage = myDocument.addImage(...);

outterImage 很可能是 img 的副本,而不是 img 本身。

有关更多详细信息,请查看 C++ 中的实例生命周期。

于 2012-06-15T04:11:01.460 回答
1

要初始化一个新指针,您需要使用new关键字。

CImage * img = new CImage();

这在堆上分配了一部分内存(内存的非本地部分),并在CImage那里创建对象。然后,CImage它获取指向该对象的指针并返回它,即使在函数离开其当前范围后,您也可以访问该对象。这是你应该做的。

但是,如果这样做,您可能会发现在代码返回后您CImage img = CImage();将无法引用该对象。CImage这是因为当您声明一个本地对象(不使用new)时,它存在于堆栈(内存的另一部分)中,并在函数返回时立即被销毁。这意味着即使您有一个指向它的指针,该对象也会消失,因此尝试访问它会给您一个段错误。

于 2012-06-15T04:10:59.663 回答