boost::optional vs T*

2019-06-15 00:15发布

问题:

I'm trying to understand when is the right time to use some of the structures that come with boost and had a question regarding the use of boost::optional with a reference.

Suppose I have the following class, using boost::optional:

class MyClass {
public:
   MyClass() {}

   initialise(Helper& helper) {
      this->helper = helper;
   }

   boost::optional<Helper&> getHelper() {
      return helper;
   }

private:
   boost::optional<Helper&> helper;
}

Why would I use the above instead of:

class MyClass {
public:
   MyClass() : helper(nullptr) {}

   initialise(Helper& helper) {
      this->helper = &helper;
   }

   Helper* getHelper() {
      return helper;
   }

private:
   Helper* helper;
}

They both convey the same intent, i.e. that getHelper could return null, and the caller still needs to test if a helper was returned.

Should you only be using boost::optional if you need to know the difference between 'a value', nullptr and 'not a value'?

回答1:

Compared to a raw pointer, an optional reference may suggest that (1) pointer arithmetic is not used, and (2) ownership of the referent is maintained elsewhere (so delete will clearly not be used with the variable).



回答2:

Great question, and John Zwinck's answer above is right. However, some people (e.g., many on the standardization committee), doubt whether these reasons are enough to justify the existence of optional<T&>, when optional<T&> can have such confusing semantics. Consider what should happen when you assign to one of these guys. Should it re-seat the reference (i.e., make it point to a different object), or assign through the reference, like a real T& does? A case can be made for either, which would cause confusion and subtle bugs. Support for optional<T&> was removed from the proposal that recently got accepted into the C++14.

In short, if you want to make your code portable to C++14's std::optional, prefer T* over boost::optional<T&>.