C++ 在类引用中使用或不使用指针。什么';有什么区别?

C++ 在类引用中使用或不使用指针。什么';有什么区别?,c++,pointers,C++,Pointers,我有返回一个对象的函数,但我不知道应该返回对象本身还是指向对象的指针 以下是我的函数示例: CImage CDocument::AddImage(string Name, string fileName) { CImage img = CImage(); img.Name = Name; img.Path = fileName; img.IwImage = Iw2DCreateImage(&fileName[0]); Images.push_ba

我有返回一个对象的函数,但我不知道应该返回对象本身还是指向对象的指针

以下是我的函数示例:

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++非常陌生,所以请容忍我。

< P>初始化一个新指针,你需要使用<代码>新< /Cord>关键字。
CImage * img = new CImage();
这在堆上分配了一部分内存(内存的非本地部分),并在那里创建
CImage
对象。然后,它获取一个指向该
CImage
对象的指针并返回它,即使在函数离开其当前作用域后,您也可以访问该对象。这是你应该做的


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

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

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


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

首先修复指针部分:

CImage * img = new CImage();
修复编译器错误

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

第一个示例将在函数结束时销毁(并释放内存)-这可能会导致意外行为,具体取决于
图像的实现。向后推

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

CImage outterImage = myDocument.addImage(...);
outterImage很可能是img的副本,而不是img本身


<更多细节请检查C++中的实例生命周期.

首先指针部分的修复:

CImage * img = new CImage();
修复编译器错误

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

第一个示例将在函数结束时销毁(并释放内存)-这可能会导致意外行为,具体取决于
图像的实现。向后推

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

CImage outterImage = myDocument.addImage(...);
outterImage很可能是img的副本,而不是img本身


<> P>详细说明C++中的实例生命周期检查。

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

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


一个更好的方法是使用智能指针,如代码> STD::SysDypPTR < /C> >,它将自动管理代码“>删除”/“代码>”。该代码中存在多个问题,在C++中编码时理解的基本区别是堆栈分配和堆分配之间的差异。当您执行

CImage img=CImage()时在堆栈上创建对象。此对象在函数结束时自动销毁。现在,如果返回指向该对象的指针,调用方将获得指向无效内存位置的指针,因为该对象已被销毁。您还将此对象的地址推送到向量中,一旦函数结束,向量将再次无效。
文件名也存在同样的问题

要解决这个问题,您需要从堆中分配内存,以便在函数结束时不会破坏对象。您可以在C++中使用“代码>新< /COD>”在堆上分配对象。因此,您的代码将成为
CImage*pIma