Re: shared_ptr and const
Tim H wrote:
I understand the semantics of why this works the way it does. But I
wonder if there's a reason for the behaviore at the line marked
"QUESTION". I figured if there is an answer, someone here knows it.
Specifically, part 1 is obvious to most anyone. Part 2 is isomorphic
to part 1, yet behaves differently. If a shared_ptr is const, should
it really allow non-const dereferences?
Thanks,
Tim
#include <boost/shared_ptr.hpp>
int main(void)
{
// part 1
int *pi = new int(1);
const int *cpi = new int(2);
*pi = 11; // ok
*cpi = 22; // compile error
// part 2
boost::shared_ptr<int> spi(new int(3));
const boost::shared_ptr<int> cspi(new int(4));
*spi = 33; // ok
*cspi = 44; // QUESTION: should this be a compile
error?
As someone already replied you confuse "const int*" which is actually
equivalent to "int const*" and shared_ptr<const int> with "int* const"
which is equivalent to "const shared_ptr<int>" (or "shared_ptr<int>
const").
In the first case it's the memory pointed to that is constant. In the second
case it's the pointer itself (or shared_ptr) that is constant.
Generally prefer the form of "T const*" over to "const T*" because:
1. it doesn't create such confusions
2. it will not give you strange errors when dealing with template code and
typedefs, example of such code(quote from C++ Templates Complete Guide):
typedef char* CHARS;
typedef CHARS const CPTR; // constant pointer to chars
The meaning of the second declaration is preserved when we textually replace
CHARS with what it stands for:
typedef char* const CPTR; // constant pointer to chars
However, if we write const before the type it qualifies, this principle
doesn't apply. Indeed, consider the alternative to our first two type
definitions presented earlier:
typedef char* CHARS;
typedef const CHARS CPTR; // constant pointer to chars
Textually replacing CHARS results in a type with a different meaning:
typedef const char* CPTR; // pointer to constant chars
typedefs are textually replaced thus can get into errors when using const
before the const type.
// part 3
boost::shared_ptr<const int> spci(new int(5));
const boost::shared_ptr<const int> cspci(new int(6));
*spci = 44; // compile error
*cspci = 55; // compile error
return 0;
}
shared_ptr<> tries to behave like a normal pointer/reference. And with
pointer/references you have what is called "bitwise constness" as oposed
to "logical constness", ie having a const pointer ("int* const pi = &i")
doesn't restrict the access to the memory pointed to, it just restricts the
access to the pointer itself ("pi = &another;" will error but "*pi = 10"
will not).
In conclusion, if you don't want non-const access to the pointed to object
then make it "shared_ptr<T const>" and not "shared_ptr<T> const". They are
very different...
--
Dizzy