Short blog here, just pointing out a weird problem I ran into the other day in the handling of shared_ptr
s. I have some classes that keep shared_ptr
members, and sometimes I need to hand out more references to callers... you know, share them. That getter might look a bit like this:
class Klass
{
public:
shared_ptr<int> GetX() { return x; }
const shared_ptr<int> GetX() const { return x; }
shared_ptr<int> x;
};
Right? Looks good? That's the normal way I write my pointers, anyway. But... there's something wrong here, and maybe you've already spotted it. Here's the code that triggers it, anyway.
int __cdecl wmain(int argc, wchar_t* argv[])
{
Klass k;
k.x = shared_ptr<int>(new int(3));
const Klass* pk = &k;
shared_ptr<int> spX(pk->GetX()); // invokes const GetX()
*spX = 13;
wprintf(L"x: %d\n", *spX); // x: 13
return 0;
}
Hey, wait a second! This invokes the const
getter, but then the caller is able to modify the value. How did that circumvent the const
? Well, the problem is that you returned a const shared_ptr<int>
value, pointing to a non-const int
, so the shared_ptr
object can't be modified, but the thing it points to can. Moreover, since it's returning a value (rather than a pointer), the const
doesn't even matter.
The fix is simple. Here ya go:
shared_ptr<const int> GetX() const { return x; }
// and later in wmain()
shared_ptr<const int> spX(pk->GetX()); // invokes const GetX()
Now we get a compiler error, as we want:
main.cpp(35) : error C3892: 'spX' : you cannot assign to a variable that is const
This difference is analogous to the difference in constness on raw pointer types: int* const
vs const int*
(same as int const*
). These rules don't seem very inuitive or nice, but you should know them if you're trying to make your code correct.
1 comments:
legeeeit
Post a Comment