473,396 Members | 1,784 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

shared_ptr and const

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<intspi(new int(3));
const boost::shared_ptr<intcspi(new int(4));

*spi = 33; // ok
*cspi = 44; // QUESTION: should this be a compile
error?

// part 3
boost::shared_ptr<const intspci(new int(5));
const boost::shared_ptr<const intcspci(new int(6));

*spci = 44; // compile error
*cspci = 55; // compile error

return 0;
}

May 28 '07 #1
14 6595
Tim H wrote:
>
// part 2
boost::shared_ptr<intspi(new int(3));
const boost::shared_ptr<intcspi(new int(4));

*spi = 33; // ok
*cspi = 44; // QUESTION: should this be a compile
error?
ANSWER: no. cspi is a const pointer to int, not a pointer to const int.
The analogous pointer would be:

int * const cip;

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
May 28 '07 #2
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<intspi(new int(3));
const boost::shared_ptr<intcspi(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 intwith "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 intspci(new int(5));
const boost::shared_ptr<const intcspci(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<Tconst". They are
very different...

--
Dizzy

May 29 '07 #3
On May 29, 6:11 am, Dizzy <d...@roedu.netwrote:
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 ashared_ptris 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<intspi(new int(3));
const boost::shared_ptr<intcspi(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*" andshared_ptr<const intwith "int* const"
which is equivalent to "constshared_ptr<int>" (or "shared_ptr<int>
const").
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<Tconst". They are
very different...

I fully apprciate the literal difference. What I am curious about is
parallelism to native pointers.

WHY is it so? Why would it be a bad idea to sub-class shared_ptr and
make "operator->() const" and "operator*() const" return const
references?

The parallel usage is what I want.

const int *cpi = new int;
const shared_ptr<intshcpi = new int;

*cpi = 2;
*thcpi = 2;

This example is trivial to change, but every piece of code I see does

typedef shared_ptr<intint_ptr;

So now we always have to have a second typedef for const_int_ptr;

Whipping up a trivial sub-class is easy. So why is it a bad idea?

Thanks,

Tim

Jun 1 '07 #4
On Jun 1, 3:50 am, Tim H <thoc...@gmail.comwrote:
On May 29, 6:11 am, Dizzy <d...@roedu.netwrote:
Tim H wrote:
WHY is it so? Why would it be a bad idea to sub-class shared_ptr and
make "operator->() const" and "operator*() const" return const
references?
Because this doesn't mimic the way raw pointers work; it has
counter intuitive semantics.
The parallel usage is what I want.
const int *cpi = new int;
const shared_ptr<intshcpi = new int;
But those aren't parallel. The parallels would be:
int const* cpi = new int ;
shared_ptr< int const shcpi = new int ;
or
int* const cpi = new int ;
shared_ptr< int const shcpi = new int ;

A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* p0 ;
int const* p1 ;
int* const p2 ;
int* const* p3 ;
gives:
shared_ptr< int p0 ;
shared_ptr< int const p1 ;
shared_ptr< int const p2 ;
shared_ptr< int const const p3 ;

More generally, "shared_ptr<T>" mimics "T*".
*cpi = 2;
*thcpi = 2;
This example is trivial to change, but every piece of code I see does

typedef shared_ptr<intint_ptr;
So now we always have to have a second typedef for const_int_ptr;
And how is this any different than with a raw pointer?
Whipping up a trivial sub-class is easy. So why is it a bad idea?
Because the results aren't really a "smart pointer", and don't
behave intuitively.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 1 '07 #5
On Jun 1, 6:32 am, James Kanze <james.ka...@gmail.comwrote:
WHY is it so? Why would it be a bad idea to sub-class shared_ptr and
make "operator->() const" and "operator*() const" return const
references?

Because this doesn't mimic the way raw pointers work; it has
counter intuitive semantics.
I beg to differ, here.

I can not take all my code that uses "foo *" and "const foo *" and
drop in my typedef'ed foo_ptr. Instead I need to drop in a 2nd
typedef.
This example is trivial to change, but every piece of code I see does
typedef shared_ptr<intint_ptr;
So now we always have to have a second typedef for const_int_ptr;

And how is this any different than with a raw pointer?
If I have "foo *" and want to qualify it as const, I simply add
"const" before it. If I have a typedef'ed "foo_ptr", and I want to
change it to a const, I add a second typedef and change the typedef I
am using.

It's the lack of being able to globally search and replace "foo *"
with "foo_ptr" that irks me.
Whipping up a trivial sub-class is easy. So why is it a bad idea?

Because the results aren't really a "smart pointer", and don't
behave intuitively.
If I say that they behave intuitively for me, is there any caveat or
reason I should not do this for my own code?

Jun 1 '07 #6
On Jun 1, 5:27 pm, Tim H <thoc...@gmail.comwrote:
On Jun 1, 6:32 am, James Kanze <james.ka...@gmail.comwrote:
WHY is it so? Why would it be a bad idea to sub-class shared_ptr and
make "operator->() const" and "operator*() const" return const
references?
Because this doesn't mimic the way raw pointers work; it has
counter intuitive semantics.
I beg to differ, here.
I can not take all my code that uses "foo *" and "const foo *" and
drop in my typedef'ed foo_ptr. Instead I need to drop in a 2nd
typedef.
In place of what? If you have:
typedef foo* FooPtr ;
you can replace it trivially with:
typedef shared_ptr< foo FooPtr ;
with exactly the same behavior.

If you have "foo*" and "foo const*", obviously, you'll need two
different shared_ptr. The same as if you had "foo*" and "bar*".
It's more or less the same relationship.
This example is trivial to change, but every piece of code I see does
typedef shared_ptr<intint_ptr;
So now we always have to have a second typedef for const_int_ptr;
And how is this any different than with a raw pointer?
If I have "foo *" and want to qualify it as const, I simply add
"const" before it.
You can, but it's a lot clearer if you add the const after the
foo. Const normally modifies what precedes it.
If I have a typedef'ed "foo_ptr", and I want to
change it to a const, I add a second typedef and change the typedef I
am using.
Exactly the same as with a pointer. If you typedef a pointer,
and what to change it to point to const, you need a second
typedef.
It's the lack of being able to globally search and replace "foo *"
with "foo_ptr" that irks me.
Whipping up a trivial sub-class is easy. So why is it a bad idea?
Because the results aren't really a "smart pointer", and don't
behave intuitively.
If I say that they behave intuitively for me, is there any caveat or
reason I should not do this for my own code?
Because it confuse anyone who knows C++? Because it violates
the type system? Because it links the const-ness of two
different, unrelated objects?

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 1 '07 #7

James Kanze <ja*********@gmail.comwrote in message ...

/* """
A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* p0 ;
int const* p1 ;
int* const p2 ;
int* const* p3 ;
gives:
shared_ptr< int p0 ;
shared_ptr< int const p1 ;
shared_ptr< int const p2 ;
shared_ptr< int const const p3 ;

""" */
int * const *p3 ;
The 'int' is read-write, the 'pointer-to-pointer' is read-only, '*p3' is rw:
shared_ptr< int const const p3 ;
So, this p3 does not look correct to me (i am not familiar with boost).
Seems to me like it might be (?):

shared_ptr< int * const p3 ;
or:
shared_ptr< int const *p3 ;
or:
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'
or?

Just because I don't need/use them now doesn't mean that someday I might
desperately need shared_ptr<>. Could you clarify this point?

[ Dang, now I need to re-review Alf's 'Pointer' PDF!! <G>]
--
Bob R
POVrookie
Jun 2 '07 #8
BobR schrieb:
James Kanze <ja*********@gmail.comwrote in message ...

/* """
A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* p0 ;
int const* p1 ;
int* const p2 ;
int* const* p3 ;
gives:
shared_ptr< int p0 ;
shared_ptr< int const p1 ;
shared_ptr< int const p2 ;
shared_ptr< int const const p3 ;
Are you sure about p3?

int const* const p3;
gives:
shared_ptr< int const const p3 ;

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Jun 2 '07 #9

Thomas J. Gritzan <Ph*************@gmx.dewrote in message...
BobR schrieb:
James Kanze <ja*********@gmail.comwrote in message ...

/* """
A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* const* p3 ;
gives:
shared_ptr< int const const p3 ;

Are you sure about p3?

int const* const p3;
gives:
shared_ptr< int const const p3 ;
Hi Thomas,

Are you answering me or James?
( I used makeshift quotes /* """ ... """ */ for James' post.).

I was asking about James':
int * const *p3;

My 'guess' ( assuming 'shared_ptr' is nestable):
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'?

Does that seem correct?

I don't have 'boost', so, I can't 'test' it (I'll wait for TR1 or?).
Thanks.
--
Bob R
POVrookie
Jun 2 '07 #10
On Jun 1, 3:32 pm, James Kanze <james.ka...@gmail.comwrote:

Sorry about this: there's an obvious error in the following:
A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* p0 ;
int const* p1 ;
int* const p2 ;
int* const* p3 ;
This last line should be:

int const* const p3 ;
gives:
shared_ptr< int p0 ;
shared_ptr< int const p1 ;
shared_ptr< int const p2 ;
shared_ptr< int const const p3 ;
More generally, "shared_ptr<T>" mimics "T*".
--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 3 '07 #11
On Jun 2, 2:01 am, "BobR" <removeBadB...@worldnet.att.netwrote:
James Kanze <james.ka...@gmail.comwrote in message ...

/* """
A shared_ptr mimics the semantics of the pointer. And the
const-ness of the pointer is orthogonal to the const-ness of
what is pointed to:
int* p0 ;
int const* p1 ;
int* const p2 ;
int* const* p3 ;
gives:
shared_ptr< int p0 ;
shared_ptr< int const p1 ;
shared_ptr< int const p2 ;
shared_ptr< int const const p3 ;

""" */
int * const *p3 ;
The 'int' is read-write, the 'pointer-to-pointer' is read-only, '*p3' is rw:
shared_ptr< int const const p3 ;
So, this p3 does not look correct to me (i am not familiar with boost).
The error is in the raw pointer line, where I duplicated the *,
and not the const, like I meant to. The above is the equivalent
of:

int const* const p3 ;
Seems to me like it might be (?):
shared_ptr< int * const p3 ;
or:
shared_ptr< int const *p3 ;
or:
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'
or?
The last. They're nestable. Not that I think that you ever
should nest them. (In practice, I don't use them very often
anyway.)
Just because I don't need/use them now doesn't mean that someday I might
desperately need shared_ptr<>. Could you clarify this point?
If you can't use Boost, Barton and Nackman have an example of a
very similar shared_ptr.

--
James Kanze (Gabi Software) email: ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 3 '07 #12
BobR wrote:
[...]
Hi Thomas,

Are you answering me or James?
( I used makeshift quotes /* """ ... """ */ for James' post.).
I was answering to you, since I didn't notice the quotes (BTW why is
everyone using non-standard quotes?)
But you are right, it should be a reply to James.
I was asking about James':
int * const *p3;

My 'guess' ( assuming 'shared_ptr' is nestable):
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'?
As James already explained else thread, it should be
int const* const p3;

A nested shared_ptr<rarely would make sense.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Jun 3 '07 #13

James Kanze wrote in message...

/* """ // <--- note the quote <G>
On Jun 2, 2:01 am, "BobR" wrote:
int * const *p3 ;
The 'int' is read-write, the 'pointer-to-pointer' is read-only, '*p3' is
rw:
shared_ptr< int const const p3 ;
So, this p3 does not look correct to me (i am not familiar with boost).
The error is in the raw pointer line, where I duplicated the *,
and not the const, like I meant to. The above is the equivalent
of:
int const* const p3 ;
Seems to me like it might be (?):
[snip]
or:
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'
or?
The last. They're nestable. Not that I think that you ever
should nest them. (In practice, I don't use them very often
anyway.)
""" */

Yeah, I use them *very* little. That's why I wanted to clarify the issue.
Thank you very much.

/* """
Just because I don't need/use them now doesn't mean that someday I might
desperately need shared_ptr<>. Could you clarify this point?
If you can't use Boost, Barton and Nackman have an example of a
very similar shared_ptr.
""" */

It's not that I can't use 'boost', it's that I don't have it yet. :-}
I prefer to write my own 'clean-up' code for now (learning thing).
I'll probably use 'shared_ptr' when it is incorporated into the standard.

Thanks again, James.

--
Bob R
POVrookie
Jun 3 '07 #14

Thomas J. Gritzan wrote in message...
BobR wrote:
[...]
Hi Thomas,
Are you answering me or James?
( I used makeshift quotes /* """ ... """ */ for James' post.).

I was answering to you, since I didn't notice the quotes
** (BTW why is everyone using non-standard quotes?) **
Older newsreaders. (I have recently come *up* to OE5!! <G>[1])
But you are right, it should be a reply to James.
I was asking about James':
int * const *p3;

My 'guess' ( assuming 'shared_ptr' is nestable):
shared_ptr< shared_ptr< int const p3 ; // are they 'nestable'?

As James already explained else thread, it should be
int const* const p3;

A nested shared_ptr<rarely would make sense.
I agree. I just wanted to clarify the syntax (for future).

Thanks Thomas.

[1] - Homey don't play (or pay) ms.
--
Bob R
POVrookie
Jun 3 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Derek | last post by:
Something puzzles me about Boost's shared_ptr implementation: template <typename T> class shared_ptr { public: T* operator->() const { return p; }
6
by: Ryan Mitchley | last post by:
Hi all Given bool bResult; shared_ptr<cSampleData> pNewData; shared_ptr<cBase> pNewBase; where cSampleData is descended from cBase, the following gives me a valid pNewData to the correct...
14
by: PengYu.UT | last post by:
In the following program, I want an iterator contain pointer pointing to constant object not const pointer. If it is possible would you please let me know how to do it? #include...
6
by: Toby Bradshaw | last post by:
Hi, Consider the following: class A { public: virtual bool foo() = 0; };
3
by: zl2k | last post by:
hi, all Here is what I want to do: to wrap my self defined class in a shared_ptr and then insert it into the priority_queue. The priority_queue should pump the least element of the self defined...
3
by: Tim H | last post by:
I'm newish to C++ but not to C. I'm confused by this code. test1() is fine. test2() fails to compile. /tmp/inherit_ptr.cpp: In function âvoid test2()â: /tmp/inherit_ptr.cpp:52: error: no...
8
by: er | last post by:
Hi All, could anyone make a suggestion to fix the code below? Thanks! class A{ public: /* constructor */ double value()const{/* implementation */}; }; typedef...
5
by: Fokko Beekhof | last post by:
Hello all, please consider the following code: -------------------------------------------------- #include <tr1/memory> struct BaseA { int x;
5
by: .rhavin grobert | last post by:
are there any pro's and con's in using references to shared_ptr<>'s ? example: __________________________________________________ void obj::foo(shared_ptr<>); vs. void...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.