C++ 依赖布尔值访问指针

C++ 依赖布尔值访问指针,c++,pointers,C++,Pointers,我有一个名为MyClass的类,它包含一个指向对象的指针,如下所示: class MyClass { public: MyClass() : _blob(nullptr) {} ~MyClass() { free(); } void generate() { if(!_blob) _blob = new Blob; } void free() { if(_blob) { d

我有一个名为
MyClass
的类,它包含一个指向对象的指针,如下所示:

class MyClass {
public:
    MyClass() : _blob(nullptr) {}
    ~MyClass() { free(); }

    void generate() {
        if(!_blob)
            _blob = new Blob;
    }

    void free() {
        if(_blob) {
            delete _blob;
            _blob = nullptr;
        }
    }

    Blob* getBlob() { return _blob; }

private:
    Blob *_blob;
};
它持有一个指向堆分配对象的指针而不在堆栈上包含它的原因是因为一些
MyClass
实例没有为此对象分配数据,因此在访问它之前,我需要检查它是否不是空指针:

if(myClass->getBlob())
    myClass->getBlob()->doSomething();
现在我有了存储一个名为
\u hasBlob
的bool变量的想法,然后像这样使用它

if(myClass->hasBlob())
    myClass->getBlob()->doSomething();

这被认为是更快和合法的吗?或者这被认为是一种不好的做法,因为我可以看到以某种方式终止对nullptr的引用的潜在危险。

通常,您会期望
MyClass::getBlob()
在您请求时总是给您一个有效的对象。因此,总体而言,我的建议是按如下方式实施该方法:

Blob* getBlob() { 
  if(_blob == nullptr) { 
     _blob = new Blob; 
     // Or call private method generateBlob, if there is a lot of logic
  }

  return _blob; 
}
或者,如果默认构造的
Blob
s很小,并且您没有那么多
MyClass
实例,那么您可以在构造函数中创建
Blob
对象,并让
getBlob
返回一个引用,这样,一旦有了有效的
MyClass
对象,就不必检查任何内容

如果要避免自动创建
Blob
对象,可以添加
hasBlob
检查,但不保留单独的布尔值,我只将其实现为

bool hasBlob() const { return _blob != nullptr; }
此函数几乎可以确定是内联的,不会占用任何额外的存储空间,并且它保证了正确的结果(例如,如果您设置
\u hasBlob=true
,然后分配
Blob
,则永远不会发生这种情况)。正如您所说,仍然存在取消引用空指针的风险,但正如您清楚地记录(希望如此)的那样,
getBlob
可能会返回空指针,如果没有为该实例分配Blob,则该风险现在由调用方承担,他们应该注意检查结果,就像任何返回指针的函数一样。事实上,这个解决方案与您已经拥有的代码完全相同,因为
if(myObject->getBlob())
现在执行的检查与
if(myObject->hasBlob())
完全相同——唯一的区别是后者可能稍微自我记录


由于您在评论中表示担心性能:我怀疑针对
null
检查指针相当快,但与往常一样,如果您想确定,通常的建议“Measure it!”适用。例如,您可能会发现,由于在我的第一个版本的
getBlob
中进行了额外的检查,编译器将不会内联函数

这是合法的,但是多余的。不是更快。事实上,虽然检查本身同样快,但保持布尔值与指针的有效性同步稍微慢一些。最糟糕的是,要证明布尔值总是同步的维护负担。一旦它被实现并被证明是正确的,它就是多余的,是对内存的浪费。

它是多余的,因此很臭。一个很好的函数,但是让它测试指针!无需在某处复制该信息。您应该使用
std::unique\u ptr
并避免所有的混乱。顺便说一句,只需检查
nullptr
就可以了。这违反了德米特定律,不要问。让myClass->doSomething()执行空值检查并在不为空时转发调用,怎么样?@HappyCoder我编辑了我的帖子。它的定义类似于
bool hasBlob()const{return\u hasBlob;}
问题是,我处理的函数可能每秒查询
getBlob()
(如果存在,可能会使用它)数千次。所以我认为bool检查会更快。OP说“一些MyClass实例没有为此对象分配数据”,这可能会导致创建许多“identity”blob对象。我不想要that@Pilpel编辑。请让我知道答案现在是否对您有用,否则我将删除它。另一条评论正好回答了我的要求。谢谢你!这不仅仅是多余的,在这种情况下,添加bool可以使类的大小增加一倍。@ChrisR。说得好。我假设这个类是一个更大的例子。也没有提到会有多少实例。如果会有很多,那么大小差异会显著影响缓存性能。@ChrisR。为什么呢?sizeof(bool)应该是1字节,sizeof(ptr)通常是4字节。@Pilpel
sizeof(bool)
不一定是1,但即使是,类的对齐要求至少是指针的对齐要求,这很可能是指针的大小,因此内存布局必须填充为指针大小的倍数才能满足对齐要求。看见