Malloc on a struct containing a std::vector

后端 未结 5 433
甜味超标
甜味超标 2021-01-14 18:30

Here is the situation :

I use a malloc to allocate memory for a struct. The struct contains various items such as pointers, string variables and vectors.

The

5条回答
  •  深忆病人
    2021-01-14 18:49

    None of the other answers appear to explain what the compiler is doing. I'll try to explain.

    When you call malloc the program reserve some memory space for the struct. That space is filled with memory garbage, (i.e. random numbers in place of the struct fields).

    Now consider this code:

    // (tested on g++ 5.1.0 on linux)
    #include 
    #include 
    
    struct S {
      int a;
    };
    
    int main() {
      S* s = (S*)malloc(sizeof(S));
      s->a = 10;
    
      *((int*)s) = 20;
    
      std::cout << s->a << std::endl; // 20 
    }
    

    So when accessing a member of a struct you are actually accessing a memory position, there should be no unexpected behavior when writing to it.

    But in C++ you can overload operators. Now imagine what would happen if the overloaded assignment operator need the class to be initialized, like in the code below:

    // (tested on g++ 5.1.0 on linux)
    #include 
    #include 
    
    class C {
      public:
      int answer;
      int n;
      C(int n) { this->n = n; this->answer = 42; }
      C& operator=(const C& rhs) {
        if(answer != 42) throw "ERROR";
        this->n = rhs.n; return *this;
      }
    };
    
    struct S {
      int a;
      C c;
    };
    
    int main() {
      S* s = (S*)malloc(sizeof(S));
    
      C c(10);
      C c2(20);
    
      c = c2; // OK
    
      std::cout << c.n << std::endl; // 20
    
      s->c = c; // Not OK
                // Throw "ERROR"
    
      std::cout << s->c.n << std::endl; // 20
    }
    

    When s->c = c is executed the assignment operator verifies if s->c.answer is 42, if its not it will throw an error.

    So you can only do as you did in your example if you know that the overloaded assignment operator of the class std::vector does not expect an initialized vector. I have never read the source code of this class, but I bet it expects.

    So its not advisable to do this, but its not impossible to be done with safety if you really need. You just need to be sure you know the behavior of all assignment operators you are using.

    In your example, if you really need an std::vector on the struct you can use a vector pointer:

    class MyClass { ... };
    
    struct S {
      std::vector* vec;
    }
    
    int main() {
      S s;
      MyClass c;
      s.vec = new std::vector();
      s.vec->push_back(c);
    }
    

提交回复
热议问题