Home > Net >  C - Object destruct itself and cant reach variables
C - Object destruct itself and cant reach variables

Time:10-18

I'm newbee about c and I'm having trouble with destructors. When i create an object and push to a vector that holds class, i can see variable "_path" is initialized. But after i try to reach the variable, i see object calls decontsuctor and i cant see the variable.

Here is the code:

#include <iostream>
#include <vector>
#include <string>

#include "ClassA.h"


A returnA(const char* char_a)
{
    return A(char_a);
}

int main() {    
    std::vector<A> vectorA;

    for (int i = 0; i < 10; i  )
    {
        std::string s = std::to_string(i);
        vectorA.emplace_back(returnA(s.c_str()));
    }
    
    std::cout << "-------" << std::endl;

    for (int i = 0; i < vectorA.size(); i  )
    {
        vectorA[i].getPath();
    }

    return 0;
}
class A
{
public:
    const char* _path;

    A(const char* path);
    ~A();
    void getPath();
};

A::A(const char* path)
{
    _path = path;
    std::cout << "Obj is constructed! " << _path << std::endl;
}

A::~A()
{
    std::cout << "Obj is deconstructed! ";
    std::cout << _path << std::endl;
}

inline void A::getPath()
{
    std::cout << _path << std::endl;
}

How can i prevent objects not deconstruct themselves and reach their variables without dynamic allocation?

CodePudding user response:

    std::string s = std::to_string(i);
    vectorA.emplace_back(returnA(s.c_str()));

std::string's c_str() method returns a pointer to std::string's internal buffer that's no longer valid when the std::string gets changed in any way.

This std::string gets destroyed at the end of this for loop, and that certainly meets all "any way" requirements. This is how all objects work in C . This std::string's gets declared inside a for loop, and it gets destroyed as soon as the end of the loop ends and it iterates again (or stops).

At this point accessing this pointer becomes undefined behavior, this is what you're seeing.

As far as destructor calls: this is completely unrelated, this is simply how vectors work. When objects get added to a vector they get moved or copied into the vector itself. Additionally, a vector resizes itself, as it grows, because that's what a vector is all about. If you add an object to a vector, and then destroy the original object you'll, obviously, see the destructor getting called:

    vectorA.emplace_back(returnA(s.c_str()));

The temporary object returned from returnA gets copied/moved into the vector, here. Then this temporary object gets destroyed, and this is the destructor call you're seeing. But the vector continues to hold its copy of the emplaced object, safe and sound.

The simplest way to fix your undefined behavior is to simply replace the const char * member of your class with its own std::string (and just the parameter to the constructor accordingly. This is what std::strings for: as you move or copy them around they'll take care of all the housekeeping for you.

This, of course, won't change the destructor behavior or invocation, it does not affect that.

  •  Tags:  
  • c
  • Related