堆分配成员引用是一个可怕的想法?为什么?

Cor*_*ein 7 c++ memory heap reference

为了最好地解释这个问题,我构建了一个简单的例子.说我有一个课程Blob如下:

class Blob
{
    string personalName;
    string& familyName;
}
Run Code Online (Sandbox Code Playgroud)

A Blob可以由Creator(又名程序员)产生,此时它可以选择一个personalName,因为它有权成为第一代Blob,它可以选择它自己的familyName.

或者,Blob可以通过产生现有的东西来创建a Blob,此时它会选择它自己的personalName,但是familyNameBlob在该族中克隆的所有其他s 共享.如果Blob更改姓氏,则所有其他家庭成员将自动更改该名称.

到目前为止,这听起来都很好,直到编写Blob构造函数时我才看到:

Blob::Blob() :
    personalName(pickName()),
    familyName(pickFamilyName())
{ }

...

string& Blob::pickFamilyName()
{
    return *(new string("George"));
}   // All Blobs have family name "George" in this example
Run Code Online (Sandbox Code Playgroud)

伊克!在堆上分配内存然后将其分配给引用变量?!这看起来很吓人!

我的直觉是否正确,这有什么不妥之处,或者它只对我感到陌生,因为它不是一个常见的模式?如果出现问题,那是什么?为什么这是一个糟糕的设计?

注意:通过引用计数释放堆分配的内存并在最后一个Blob被破坏时删除内存或通过其他方法释放内存非常重要.

Mar*_*som 14

将引用存储为类成员的唯一时间是:

  1. 该数据不属于该类,并且该类不负责释放它;
  2. 保证引用对象的生命周期长于包含对象的生命周期.

您的示例违反了规则1.

  • @Cory,因为定义*的引用*是指在某些其他上下文中存在的对象.你的引用是一个匿名的堆大块,当指针在`pickFamilyName`的末尾被销毁时,它的上下文消失了.一个更好的选择是智能指针. (4认同)

Daw*_*son 8

我认为它的"臭"部分是将变量存储为字符串的引用,因为很难跟踪它是否是一个有效的对象.为什么不使用类似的东西:

boost::shared_ptr<std::string> Blob::pickFamilyName()
{
    return boost::shared_ptr<std::string>(new std::string("George"));
}
Run Code Online (Sandbox Code Playgroud)

编辑

根据Praetorian的建议,您可以避免自己手动分配内存:

boost::shared_ptr<std::string> Blob::pickFamilyName()
{
    return boost::make_shared<std::string>("George");
}
Run Code Online (Sandbox Code Playgroud)

  • @CJohnson:当然你不是在争论编译时间是否特别优惠*基本*资源管理?工作程序比快速编译程序更重要. (8认同)
  • 或者甚至更好`return boost :: make_shared <std :: string>("George");` (2认同)
  • 或者现在使用std :: shared_ptr :) (2认同)