开发者

C++: Is this a valid constant member function?

开发者 https://www.devze.com 2023-04-07 06:32 出处:网络
I\'m currently working on a c++ class. The purpose of the class is to do some http queries. You create an instance specifying

I'm currently working on a c++ class. The purpose of the class is to do some http queries. You create an instance specifying

  • destination url
  • some other parameters

With this instance, you can call a method called "getChildren" which connects to the HTTP server, executes a query and returns a list of children. So basically, it looks similar to this:

class HttpRequest
{
   public:
   // omitted constructor, ...
   const std::list<Child> getChildren() {
      // do the http query
      // build a list
      return(list);
   }
}

The list which is returned by "getChildren" might change for each 开发者_如何学编程call - depending on other actions done on the HTTP server. Now what's your opinion: How shall I declare the method:

  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

It will compile in both ways, since "getChildren" doesn't modify HttpRequest.

Thanks for your help, Uli


  • const std::list<Child> getChildren();
  • const std::list<Child> getChildren() const;

It will compile in both ways, since "getChildren" doesn't modify HttpRequest.

  1. No, it will not compile both ways. (If it would, what would that difference be there for?) The second form is required to call getChildren() for const HttpRequest objects (or references or pointers):

    void f(const HttpRequest& req)
    {
       const std::list<Child>& list = req.getChildren(); // requires const
       // ...
    }
    

    This would require the trailing const.

  2. The top-level const on the return type (const std::list<Child>) makes no difference at all. The returned object is an rvalue. All you can do with it is to make a copy or bind it to a const std::list<Child>& - no matter whether it's const or not.

  3. You very likely do not want to copy such lists to be copied each time getChildren() is called, so you should return a reference:

    const std::list<Child>& getChildren() const;
    

    (Of course, if there is asynchrony involved, you might want to copy, rather than hand out references to a potentially asynchronously changing object.)

  4. You can overload based on the trailing const. Given that, you could have two versions: one for changing the list and one for getting a const list reference:

    const std::list<Child>& getChildren() const;
          std::list<Child>& getChildren();
    

    I wouldn't know whether this makes any sense in your case.


My initial gut reaction here is that if it's hard to decide, we should look at the function in more detail. Also since the HttpRequest state isn't mutated, and since it may return a different value each time, perhaps the function shouldn't be a member at all. It seems that it might make more sense as a non-member, non-friend that makes use of the HttpRequest to perform its work and return a value. Then the const-semantics are clear.


A general rule of thumb is declare a member function to be const if you can. If getChildren makes some modification that appears to change the state of the HttpRequest object it's called on (even if it doesn't actually change the state) it's possible you should declare it non-const to avoid confusing people. But otherwise, it should be const.

As an aside, I understand the logic of why you're declaring the return value to be const. I would still suggest you not do that. With C++11 and move constructors and such, it's actually very useful (and more accurate) for it to be non-const.


If your intent is to make sure that the function does not change the state of the HttpRequest object, then you want std::list<Child> getChildren() const. There is no reason to make the std::list constant, unless you return a reference.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号