A little confused with this (const ptrs)

B

Bit byte

I have the following methods:

static void Foo::setBar(const Bar*) ; //store a copy of Bar
static const Bar* Foo::getBar(void) const ; //return an UNMODIFIABLE ptr
to our internal copy

In another part of my code , I retrieved and used Bar as follows:

....
const Bar* temp = NULL ;
....
//retrieve and use
temp = Foo::getBar();
.....
delete temp ; // <- compiler did not complain (what's happend ? - has
Foo::Bar really been deleted?)

Basicaly, this is what I want to do:

1). store a copy of Bar 'safely' in Foo
2). Be able to request a ptr to Bar and use it without being able to
modify it
3). I want Foo::setBar() to be able to replace (i.e. destroy first, then
replace) the original Foo::Bar* variable

Questions:

1). How do I do that?

I was doing this:

class Foo
{
public:
Foo(){ m_bar = NULL ;}

/* I need these static so I can use Bar* in some 'stand alone' C
callback functions*/
static void setBar(const Bar* b) {
if (m_bar) delete m_bar ;
m_bar = CopyOf(b) ;
}

static const B* getBar(void)const { return m_bar ; }
private:
Bar* m_bar ;
}

whats wrong with the above?
 
R

Rolf Magnus

Bit said:
I have the following methods:

static void Foo::setBar(const Bar*) ; //store a copy of Bar

Why a pointer, not a reference?
static const Bar* Foo::getBar(void) const ; //return an UNMODIFIABLE ptr
to our internal copy

You mean "a pointer to an UNMODIFIABLE Bar". Again, why a pointer, not a
reference?
In another part of my code , I retrieved and used Bar as follows:

...
const Bar* temp = NULL ;
...
//retrieve and use
temp = Foo::getBar();
....
delete temp ; // <- compiler did not complain (what's happend ? - has
Foo::Bar really been deleted?)

Yes, it has. Do you have any reason to believe it hasn't?
Basicaly, this is what I want to do:

1). store a copy of Bar 'safely' in Foo
2). Be able to request a ptr to Bar and use it without being able to
modify it
3). I want Foo::setBar() to be able to replace (i.e. destroy first, then
replace) the original Foo::Bar* variable

Questions:

1). How do I do that?

Well, you already are doing that. I don't see your problem.
I was doing this:

class Foo
{
public:
Foo(){ m_bar = NULL ;}

/* I need these static so I can use Bar* in some 'stand alone' C
callback functions*/

Actually, that would have to be a nonmember function declared as extern "C".
static void setBar(const Bar* b) {
if (m_bar) delete m_bar ;
m_bar = CopyOf(b) ;

Note that the above function is not exception safe. If an exception is
thrown during the execution of CopyOf(b), m_bar is invalidated.
 
B

Bit byte

Rolf Magnus wrote:
Yes, it has. Do you have any reason to believe it hasn't?
The line 'const Bar* temp = NULL ;' declares a variable temp which is
allocated on the stack. I later on ASSIGN (not allocate) the address of
a constant ptr to temp (or atleast thats what I thought I was doing) -
and then it seems I can just go ahead and destroy the const object
pointed to by ptr. So what's the bloody use of const? It it does not
protect others from modifying your 'const' object.
Well, you already are doing that. I don't see your problem.
My problem is that I want to be able to hand a objet which I can create
and modify at will within the (container class), but when handing the
object to another class etc, I want to explicitly mark the object as
'handle with care' - do not modify or else ...
It would seem that I was labouring under a misaprehension about 'const'
- since the object I had decorated as a const was summarily executed as
soon as I let it out of the confines of my class - and you do not seem
suprised, and do not see what my problem is. That is what my problem is.
The fact that the compiler did not complain - and you do not seem to
find anything 'wrong' or 'unexpected' with the snippet I presented and
the behaviour I reported, is what confuses me.

So I'll ask (perhaps a little more lucidly this time)

I want to have a class that contains an object (actually a structure) -
lets call it data type A. I want the container class to have a method
which allows it to accept a new variable of data type A, and then
replaces its previous variable of data type A with the newly received one.

This same class, will receive requests by other classes, who want to use
the object. However, I do not want any class receiving this
class/structure, to be able to modify (and certainly not delete) the
received object.

This is the problem I'm trying to solve. Any pointers (no pun intended)
wll be much appreciated.
 
M

mlimber

Bit said:
I want to have a class that contains an object (actually a structure) -
lets call it data type A. I want the container class to have a method
which allows it to accept a new variable of data type A, and then
replaces its previous variable of data type A with the newly received one.

This same class, will receive requests by other classes, who want to use
the object. However, I do not want any class receiving this
class/structure, to be able to modify (and certainly not delete) the
received object.

This is the problem I'm trying to solve. Any pointers (no pun intended)
wll be much appreciated.

A few solutions spring to mind: (1) use a reference instead of a
pointer, as Rolf suggested, since that would make it less likely (but
not impossible!) that the user would try to delete the object. (2) Use
std::tr1::shared_ptr (aka boost::shared_ptr), with which the user is
relieved of deleting the object anyway and should not try to do so. (3)
Return some other proxy object that has no public interface but is
accessible to specific friends via the attorney-client idiom (cf.
http://www.ddj.com/showArticle.jhtml?articleID=184402053).

Note that you're trying to prevent the user from making mistakes.
That's good. However, you can't prevent the user from doing all sorts
of evil if s/he refuses to be civil about things.

Cheers! --M
 
A

Andre Kostur

Rolf Magnus wrote:

The line 'const Bar* temp = NULL ;' declares a variable temp which is
allocated on the stack. I later on ASSIGN (not allocate) the address of

Are you sure that Foo:getBar() didn't allocate an object? More
importantly, how can the compiler know? Foo::getBar() may be in a
completely different translation unit altogether. And even if getBar()
does obtain the address from a container of some sort, the compiler
_still_ doesn't really know whether the pointer that was put into the
container was dynamically allocated or not.
a constant ptr to temp (or atleast thats what I thought I was doing) -
and then it seems I can just go ahead and destroy the const object
pointed to by ptr. So what's the bloody use of const? It it does not
protect others from modifying your 'const' object.

From a language perspective, destroying an object is not a "modification"
per se. It's an indication of the end of the lifetime of that object.
What you might want to do it make your destructor private and provide your
own friend function to perform disposals.
My problem is that I want to be able to hand a objet which I can create
and modify at will within the (container class), but when handing the
object to another class etc, I want to explicitly mark the object as
'handle with care' - do not modify or else ... It would seem that I was
labouring under a misaprehension about 'const' - since the object I had
decorated as a const was summarily executed as soon as I let it out of
the confines of my class - and you do not seem suprised, and do not see
what my problem is. That is what my problem is. The fact that the
compiler did not complain - and you do not seem to find anything 'wrong'
or 'unexpected' with the snippet I presented and the behaviour I
reported, is what confuses me.

Hand them back a const reference. If they take the address of that and
delete it, that's their problem.
So I'll ask (perhaps a little more lucidly this time)

I want to have a class that contains an object (actually a structure) -
lets call it data type A. I want the container class to have a method
which allows it to accept a new variable of data type A, and then
replaces its previous variable of data type A with the newly received
one.

This is starting to sound like an inadvisable course of action. It's
starting to sound like you want the user to construct the class, but the
container is responsible for destruction. Be careful how you go down this
path... it's an easy road to the dark side, er, memory leaks. That's one
reason why the STL containers take their own copy of the data they store.
This way the STL container controls the lifetime of the object (and if the
programmer deletes an item out from under the container, that's the
programmer's problem).
This same class, will receive requests by other classes, who want to use
the object. However, I do not want any class receiving this
class/structure, to be able to modify (and certainly not delete) the
received object.

Return a const-ref. Thus the caller shouldn't assume that it's allowed to
delete whatever that object is.
 
R

Rolf Magnus

Bit said:
The line 'const Bar* temp = NULL ;' declares a variable temp which is
allocated on the stack. I later on ASSIGN (not allocate) the address of
a constant ptr to temp (or atleast thats what I thought I was doing) -
and then it seems I can just go ahead and destroy the const object
pointed to by ptr. So what's the bloody use of const? It it does not
protect others from modifying your 'const' object.

It does. However, note that destroying an object doesn't count as modifying
it.

Consider this:

#include <iostream>

class X
{
public:
X(int i) : i_(i) {}
int i_;
};

void f()
{
const X* x = new X(3);

std::cout << x->i_ << '\n';

delete x;
}

Wouldn't you say that the object pointed to by x is never modified in f()?
If, not, let's go one step further:

void f()
{
const X x = 3;
std::cout << x.i_ << '\n';
}

Has the object been modified in f() now? It was created at the beginning of
the function and destroyed at the end, just like in the previous example.
If destruction counted as modification, you could basically not define any
constants at all, because they couldn't been destroyed when they go out of
scope.
My problem is that I want to be able to hand a objet which I can create
and modify at will within the (container class), but when handing the
object to another class etc, I want to explicitly mark the object as
'handle with care' - do not modify or else ...
It would seem that I was labouring under a misaprehension about 'const'
- since the object I had decorated as a const was summarily executed as
soon as I let it out of the confines of my class - and you do not seem
suprised, and do not see what my problem is. That is what my problem is.

I could have looked more carefully. Then I would probably have seen that you
thought destruction counted as modification.
I want to have a class that contains an object (actually a structure) -
lets call it data type A. I want the container class to have a method
which allows it to accept a new variable of data type A, and then
replaces its previous variable of data type A with the newly received one.

This same class, will receive requests by other classes, who want to use
the object. However, I do not want any class receiving this
class/structure, to be able to modify (and certainly not delete) the
received object.

Well, my question would be, why anyone would want to delete an object he
hasn't created himself and wasn't told to delete? Seriously, when I get a
pointer from some API function, I would never get the idea to delete it
unless the function's documentation explicitly tells me to do that.
Anything else is plain stupid.
This is the problem I'm trying to solve. Any pointers (no pun intended)
wll be much appreciated.

One thing you can do is return a reference to the object. However, the user
of your class can still take its address and delete the object. But with
the reference, the user might not have the idea to delete the object just
for fun.
C++ only offers features to protect against accidental errors, not about
deliberate sabotage.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,731
Messages
2,569,432
Members
44,832
Latest member
GlennSmall

Latest Threads

Top