CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 16

Thread: basic question

  1. #1
    Join Date
    Sep 2003
    Posts
    815

    basic question

    Hello,


    I have a hash map with int as a key and struct myStruct as the data.

    I got to the conclusion that I shuold have a pointer to the struct since I have some copy operation,

    this is how I define my table:

    typedef std::hash_map<int, myStruct*> myStructTable;

    myStructTable m_MyTable;

    I have a loop that on compilation time, number of iteration is unknown. (loop on std::list)

    on this loop I create on every iteration MyStruct

    should I create it on advance as pointer to myStructTable and allocate it with a new

    or can I creare MyStruct itself and put its address in the table

    what I mean:

    option 1: (no need to worry about deallocations)

    for(;
    {
    MyStruct myStruct;
    ....
    //my struct initialization

    m_MyTable[key] = &myStruct
    }

    option2: (deallocate my hash_map items at the destructor (m_MyTable is a class member)

    for(;
    {
    MyStruct *myStruct;
    ....
    //my struct initialization

    m_MyTable[key] = myStruct
    }

    thanks

  2. #2
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    Option 1 will not work, your map will point to invalid memory as soon as you will exit your initialization loop.

    Option 2 will work, but that is right you will have to free your items in destructor.

    I propose an option 3:

    typedef std::hash_map<int,std::auto_ptr<MyStruct>> myStructTable;

    std::auto_ptr<MyStruct> myStruct(new MyStruct);
    // init my struct
    m_MyTable[key] = myStruct;

    // no need to worry about destruction (will be done by auto ptr)
    // and address are on the heap (and not on the stack) --> still valid after init loop exit.

  3. #3
    Join Date
    Sep 2003
    Posts
    815
    thanks for option 3, i guess I'll use it

    but can you please tell me why in option 1, it will point to invalid memeory?

    thanks

  4. #4
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863
    auto_ptr can not be used in containers. Any standard complient
    compiler should not even compile code that has containers
    of auto_ptrs.

    If you want to put smart pointers into a container, then
    use reference counted pointers.
    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

  5. #5
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    auto_ptr can not be used in containers. Any standard complient
    Oh Really ? Why not ?
    Is it not possible using typedef like this:
    Code:
    typedef struct
    {
    int x;
    int y;
    } mystruct_t;
    typedef std::auto_ptr<mystruct_t> mystruct_autoptr_t;
    typedef std::hash_map<int,mystruct_autoptr_t> myStructTable;
    Does I miss something ?
    but can you please tell me why in option 1, it will point to invalid memory?
    Because in option 1, your structs are allocated on the heap, and they will be deallocated when your init method will exit, meaning that the address you copy into your hash map will point to an invalid address.

  6. #6
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    Oops mistake !
    Please replace:
    Because in option 1, your structs are allocated on the heap, and they will be deallocated when your init method will exit, meaning that the address you copy into your hash map will point to an invalid address.
    by this:

    Because in option 1, your structs are allocated on the STACK, and they will be deallocated when your init method will exit, meaning that the address you copy into your hash map will point to an invalid address.

  7. #7
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863
    Originally posted by pdurye
    Does I miss something ?
    Oh yes, you missed something. copying auto_ptrs transfers
    ownership of the object pointed to and sets the copied auto_ptr
    to null. Using containers of auto_ptrs can lead to all sorts
    of bad, bad behavior. I suggest you go look it up. Now since the
    op is "required" to use all sorts of bad programming techniques
    maybe he should toss some containers of auto_prts in there
    just to make it complete.
    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

  8. #8
    Join Date
    Sep 2003
    Posts
    815
    pdurye

    I read your explanatin about option 1, but then I don't understand something else

    suppouse I'm not using pointer to MyStruct meaning, I'll use

    typedef std::hash_map<int, myStruct> myStructTable;

    myStructTable m_MyTable;

    and the loop:

    for(;
    {
    MyStruct myStruct;
    ....
    //my struct initialization

    m_MyTable[key] = myStruct
    }

    then isn't mystruct is also invalid after finishing the loop?

    pls explain to me, becuase that's what used at the begining, when I thought no copy operation needed, so I didn't use pointers, and it worked fine, and I don't understand why (I mean after reading your explanation about option 1, this is on the stack too!)

  9. #9
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    then isn't mystruct is also invalid after finishing the loop?
    pls explain to me, becuase that's what used at the begining, when I thought no copy operation needed, so I didn't use pointers, and it worked fine, and I don't understand why (I mean after reading your explanation about option 1, this is on the stack too!)
    calling this:
    Code:
    m_MyTable[key] = myStruct
    the copy constructor of myStruct is called and the newly created object is stored into the map. Consequenly myStruct will be destroyed when init loop will exit, but its copy will remain inside the map and will persist as long as the class to which it belongs to will persist (stack or heap depends on how you create the embedding object - on the stack or on the heap -).
    As the map will call destructor of its elements you do not need to take care of freeing them. It will just be more time consuming (but if your struct is small or init called a few time do not care of this).

  10. #10
    Join Date
    Sep 2003
    Posts
    815
    thanks

  11. #11
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    Oh yes, you missed something. copying auto_ptrs transfers
    ownership of the object pointed to and sets the copied auto_ptr
    to null. Using containers of auto_ptrs can lead to all sorts
    of bad, bad behavior. I suggest you go look it up. Now since the
    op is "required" to use all sorts of bad programming techniques
    maybe he should toss some containers of auto_prts in there
    just to make it complete.
    OK see what you mean. We can get behavior problem due to the fact that copy constructor of auto_ptr is not const for the original. You are right, it was a bad idea. Thanks for explanation.

  12. #12
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863
    No, it was a good idea. If pointers must be used then a container
    of smart pointers is the right solution. It is just that you can not
    use auto_ptr, but a reference counted smart pointer would be
    fine and could easily be made thread safe.
    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

  13. #13
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    a reference counted smart pointer would be
    fine and could easily be made thread safe.
    Is there any implementation of counted smart pointers in STL ? or in Boost may be ? Let me know I will be very interested in it. If you have your own implementation, I will be interested too.
    Thanks.

  14. #14
    Join Date
    Nov 2002
    Location
    Los Angeles, California
    Posts
    3,863
    Originally posted by pdurye
    Is there any implementation of counted smart pointers in STL ? or in Boost may be ? Let me know I will be very interested in it. If you have your own implementation, I will be interested too.
    Thanks.
    Sure.:)
    I think boost has one and here is a quick example of what one
    might look like (not a template). This one is thread safe

    PHP Code:
    volatile class FOO_SMART_PTR
    {
    public:
        
    explicit FOO_SMART_PTR(FOOpFOO 0);
        ~
    FOO_SMART_PTR();
        
    FOO_SMART_PTR(const FOO_SMART_PTRptr);
        
    FOO_SMART_PTRoperator=(const FOO_SMART_PTRptr);

        
    FOOoperator*() const;
        
    FOOoperator->() const;
        
    bool operator!() const;

    private:
        
    longm_RefCount;
        
    FOOm_pFOO;
        
    void dispose();    
    };


    FOO_SMART_PTR::FOO_SMART_PTR(FOOpFOO)
                        :
    m_pFOO(pFOO), m_RefCount(new long(1))
    {
        
    }

    FOO_SMART_PTR::FOO_SMART_PTR(const FOO_SMART_PTRptr)
                        :
    m_pFOO(ptr.m_pFOO), m_RefCount(ptr.m_RefCount)
    {
        
    InterlockedIncrement(m_RefCount);
    }

    FOO_SMART_PTRFOO_SMART_PTR::operator=(const FOO_SMART_PTRptr)
    {
        if(
    this != &ptr)
        {
            
    dispose();

            
    m_pFOO ptr.m_pFOO;
            
    m_RefCount ptr.m_RefCount;
              
    InterlockedIncrement(ptr.m_RefCount);
        }
        return *
    this;
    }

    FOO_SMART_PTR::~FOO_SMART_PTR() throw()
    {
        
    dispose();
    }

    FOOFOO_SMART_PTR::operator*() const
    {
        return *
    m_pFOO;
    }

    FOOFOO_SMART_PTR::operator->() const
    {
        return 
    m_pFOO;
    }

    bool FOO_SMART_PTR::operator!() const
    {
        return 
    == m_pFOO;
    }
        
    void FOO_SMART_PTR::dispose()
    {
        if(
    InterlockedDecrement(m_RefCount) == 0)
        {
            
    delete m_RefCount;
            
    delete m_pFOO;
        }


    P.S. I WOULD BE HAPPY IF PEOPLE COULD POINT OUT ANY
    PROBLEMS WITH THIS IMPLEMENTATION
    Last edited by souldog; November 22nd, 2003 at 10:39 PM.
    Wakeup in the morning and kick the day in the teeth!! Or something like that.

    "i don't want to write leak free code or most efficient code, like others traditional (so called expert) coders do."

  15. #15
    Join Date
    Oct 2003
    Location
    France
    Posts
    44
    Code:
    FOO_SMART_PTR& FOO_SMART_PTR::operator=(const FOO_SMART_PTR& ptr)
    {
        if(this != &ptr)
        {
            dispose();
    
            m_pFOO = ptr.m_pFOO;
            *m_RefCount = InterlockedIncrement(ptr.m_RefCount);
        }
        return *this;
    }
    Something I do not understand:
    Why a dispose here ?

    By the way I found the boost reference counted smart pointer: its name is "shared_ptr":
    http://www.boost.org/libs/smart_ptr/shared_ptr.htm

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured