简体   繁体   中英

Const correctness of operator* in std::unique_ptr

Why can 'operator*' member function of std::unique_ptr be marked const ( https://en.cppreference.com/w/cpp/memory/unique_ptr/operator *) while functions like 'front()', 'back()', 'operator[]' etc in std::vector not be marked const? Both are returning non-const references to the resources they are managing.

The core problem is I can't understand the 1st part ie why we're able to mark 'operator*' as const ie how can the return type be 'T&' when the '*this' pointer in that function would be a const pointer (due to the function being marked const)?

The difference lies in the definition of a container .

A std::vector is considered a container . This means that the objects managed by a std::vector are considered parts of the vector .

The references returned from front() , back() and operator[] must be const if the vector is const . Modifying those objects will modify the vector.

A std::unique_ptr , however, is not a container . The object it manages is not considered to be part of the std::unique_ptr . This means that modifying the managed object is not considered modifying the pointer.

Therefore, using operator* on a pointer type will never change the pointer itself, and therefore the operation can always be considered const .


std::optional may provide some helpful context to this difference.

Despite having a syntax that resembles a pointer, it is effectively a container (with max_size of 1). Because it contains its managed object, its operator* must obey the same const rules that a container does.

Drew Dormann's excellent answer above resolves the core confusion that I had. Adding a summary here (since it is too long to be posted as a comment) for complete clarity.

Doubt 1 : How are we able to use T& as the return type even though std::unique_ptr::operator*() is marked a const function?

Answer 1 : std::unique_ptr just stores the pointer to the data being managed (the data itself is not stored within the class, but rather on the heap). We're able to mark its operator*() function as const because we're returning a non-const reference to the actual data being stored & since that data itself is not stored inside the class, the 'const' qualifier just makes the pointer to the data const (ie we have a const pointer) but the data that this const pointer points to is still non-const and we can bind non-const references to it.

Doubt 2 : The same thing is true for std::vector (ie the data managed by it is not stored within the class, but on the heap instead) but then why we don't similarly mark functions like std::vector::front() , std::vector::back() etc as const?

Answer 2 : This is due to the semantics associated with container classes in C++. Quoting Drew from above - std::vector models properties of an array, while a std::unique_ptr models properties of a pointer . So we kind of act as if the data managed by std::vector resides inside the class. Note that std::optional is different from std::unique_ptr / std::vector as the data being managed is actually stored within the class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM