A little confused with this (const ptrs)

Discussion in 'C++' started by Bit byte, May 14, 2006.

  1. Bit byte

    Bit byte Guest

    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?
    Bit byte, May 14, 2006
    #1
    1. Advertising

  2. Bit byte

    Rolf Magnus Guest

    Bit byte wrote:

    > 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.

    > }
    >
    > static const B* getBar(void)const { return m_bar ; }
    > private:
    > Bar* m_bar ;
    > }
    Rolf Magnus, May 14, 2006
    #2
    1. Advertising

  3. Bit byte

    Bit byte Guest

    Rolf Magnus wrote:
    <snip>
    >>
    >>...
    >>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?
    >

    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.

    >
    >>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.
    >

    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.
    Bit byte, May 15, 2006
    #3
  4. Bit byte

    mlimber Guest

    Bit byte wrote:
    > 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
    mlimber, May 15, 2006
    #4
  5. Bit byte

    Andre Kostur Guest

    On Mon, 15 May 2006 15:56:34 +0100, Bit byte wrote:

    > Rolf Magnus wrote:
    > <snip>
    >>>
    >>>...
    >>>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?
    >>

    > 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.

    >>>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.
    >>

    > 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.

    > This is the problem I'm trying to solve. Any pointers (no pun intended)
    > wll be much appreciated.
    Andre Kostur, May 15, 2006
    #5
  6. Bit byte

    Rolf Magnus Guest

    Bit byte wrote:

    >>>...
    >>>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?
    >>

    > 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.

    >>>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.
    >>

    > 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.
    Rolf Magnus, May 15, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thomas Matthews

    Ptrs to member funcs & inheritance

    Thomas Matthews, Dec 20, 2003, in forum: C++
    Replies:
    2
    Views:
    381
    David White
    Dec 20, 2003
  2. B. Deepak
    Replies:
    1
    Views:
    512
    Kerem OZMAN
    May 23, 2006
  3. richard

    Re: qsort and structs and ptrs

    richard, Aug 14, 2003, in forum: C Programming
    Replies:
    0
    Views:
    385
    richard
    Aug 14, 2003
  4. LBJ

    using volatile ptrs ...

    LBJ, Nov 10, 2004, in forum: C Programming
    Replies:
    6
    Views:
    404
    Lawrence Kirby
    Nov 12, 2004
  5. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
Loading...

Share This Page