C++: Is this a valid constant member function?
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.
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()
forconst 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
.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 aconst std::list<Child>&
- no matter whether it'sconst
or not.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.)
You can overload based on the trailing
const
. Given that, you could have two versions: one for changing the list and one for getting aconst
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.
精彩评论