![](/img/trans.png)
[英]What's the difference between defining class methods in a namespace block and defining them using ::
[英]Using pointers or not using them for class references. What's the difference?
我有返回对象的函数,但是我很困惑应该返回对象本身还是指向对象的指针?
这是我的功能的一个例子:
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 ++很陌生,请耐心等待。
这段代码有很多问题,要理解使用C ++进行编码时的基本区别是堆栈分配和堆分配。 当您执行CImage img = CImage();
该对象是在堆栈上创建的。 函数结束后,该对象将自动销毁 。 现在,如果您返回指向该对象的指针,则由于该对象已被销毁,因此调用者将获得指向无效内存位置的指针。 您还将这个对象的地址压入向量中,一旦函数结束,它将再次无效。 fileName
也存在相同的问题。
要解决此问题,您需要从堆中分配内存,以便函数结束时不会破坏对象。 您可以使用C ++中的new
在堆上分配对象。 这样您的代码将变为CImage* pImage = new CImage();
。 请注意,在这种情况下,您有责任使用delete
释放内存。 因此,您可以使用此技术将函数更改为返回CImage*
。 您也可以将此指针推入矢量Images
。 请注意,要释放为CImage
对象分配的内存,您需要遍历Images
向量并在每个指针上显式调用delete
。
更好的方法是在这种情况下使用智能指针,例如std::shared_ptr
,它将为您自动管理delete
的调用。
首先修复指针部分:
CImage * img = new CImage();
修复了编译器错误。
考虑实例寿命。 一个类的实例在到达其作用域的末尾时便被销毁-这是该函数的右括号。
第一个示例将在函数末尾销毁img(并释放其内存)-根据Images.push_back
的实现,这可能会引起意想不到的行为。
对于返回的实例,如果调用代码看起来像这样,则很可能会创建变量的副本:
CImage outterImage = myDocument.addImage(...);
outterImage很可能是img的副本,而不是img本身。
有关更多详细信息,请检查C ++中的实例生命周期。
要初始化新指针,您需要使用new
关键字。
CImage * img = new CImage();
这在堆上分配了一部分内存(内存的非本地部分),并在那里创建了CImage
对象。 然后,它获取指向该CImage
对象的指针并返回它,即使在函数离开其当前作用域之后,也可以访问该对象。 这是您应该做的。
但是,如果您执行CImage img = CImage();
,您可能会发现代码返回后将无法引用CImage
对象。 这是因为当声明局部对象(不使用new
)时,该局部对象存在于堆栈(内存的另一部分)中,并在函数返回时立即销毁。 这意味着即使您有一个指向它的指针,该对象也将消失,因此尝试访问它会给您一个段错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.