简体   繁体   中英

const correctness of a member function returning a shared_ptr<>

if I have the class

class foo {
   private:
      std::shared_ptr<char> m_data;
   public:
      std::shared_ptr<const char> GetData()
      { return m_data;}
} 

I believe that std::shared_ptr< T > should cast to std::shared_ptr< const T > and share the same object, but what's the const correctness on the function?

IE is this valid?

std::shared_ptr<const char> GetData() const;
  • Does the function modify the internal state of the object? No. *

  • Does the function give its caller (or other outside environment) modification access to the internal state of the object? No.

This means it's safe to mark it as const .

* Note: @Yakk correctly pointed out in the comments that for some definition of "internal state," the function does indeed modify it, because it increments the reference counter on the char owned by the shared pointer m_data . You have to decide for yourself whether that constitutes a non-const operation; strictly by the rules of the language, it does not (because it modifies something pointed to by the shared_ptr , not the shared_ptr itself). But since you store a shared_ptr in the first place, I assume you're fine with sharing ownership, so doing it shouldn't be viewed as a modification.

You should be very careful with code like that. In the state your code is in at the moment, everything will be safe, because you're only wrapping a shared_ptr and nobody can modify the contents because they are private. However, if you extend your code there is a subtle but severe pitfall that can be hard to debug: If you add functions that modify the data to which the shared_ptr points, then code that already owns a shared_ptr to a const char from your GetData() function will see the modified data and not a copy of the data.

In C++ the keyword const really means read-only and not immutable as many think when they first learn it. A way to make your code future-proof would be to use std::shared_ptr<char> as data type for your data member m_data . If that is not appropriate for your requirements of your code, consider to just return a complete copy of your data when the function GetData() is called. Implementing copy-on-write may be necessary, if you have bad performance constraints, but unless you're sure of these performance penalties avoid copy-on-write, because it's tricky because of the reasons above.

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