3

After dynamically allocating struct, I thought it woudl be prudent to put 'delete' at the end. But it gave me a runtime error. Compiled ok, though. So if I get rid of 'delete', it runs fine. But I worry there could be a memory leak. What would be the safe way to handle this code?

#include <iostream>
#include <vector>
using namespace std;

typedef struct
{
    vector<char*> vstr;
    vector<int> vint;

}VecStrInt;

int main()
{
    VecStrInt * mtx = new VecStrInt();

    mtx[0].vstr.push_back("Hello");
    mtx[0].vint.push_back(1);

    cout<<mtx[0].vint.at(0)<<endl;
    cout<<mtx[0].vstr.at(0)<<endl;

    //delete [] mtx;

    return 0;
}
trueCodian
  • 35
  • 5
  • BTW, you may avoid new completely, `std::vector mtx;` or `VecStrInt mtx;` is enough (depending of what you want). – Jarod42 Feb 24 '15 at 13:56

3 Answers3

6

The call of delete[] is not the same as the call of delete (note the square brackets).

You pair calls of delete with calls of new, and calls of delete[] with calls of new SomeType[someCount].

In your case, you allocated a single object, not an array. Your object happens to represent a vector, which is an array, but it does not matter to C++: you allocated it with a "single" new, so you cannot apply an "array" delete[] to it.

Hence, you need to delete it using the regular delete operator:

delete mtx;

Note: there is rarely a situation when you should allocate std::vector<T> dynamically. The object that represents std::vector<T> itself is very small; the data is stored elsewhere, and is allocated dynamically. So you might as well use

VecStrInt mtx;

and skip delete altogether.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

If you allocate only a single object like this then you have to use operator delete

VecStrInt * mtx = new VecStrInt();
//...
delete mtx;

If you allocate an array of objects (even if the array contains only one element) you have to use operator delete[] like this

VecStrInt * mtx = new VecStrInt[1];
//...
delete [] mtx;

Also you could use a standard smart pointer as for example std::unique_ptr.

Shoe
  • 74,840
  • 36
  • 166
  • 272
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

If you really want to be safe, you should not use new/delete directly like this, because an exception may be thrown in the middle of your function and the delete clause will not be executed.

The C++ way of allocating and deallocating things is done through constructors/destructors and is called RAII. Standard classes handle this for you through their constructor/destructor. You can use for example :

  • standard containers like std::vector<T> for multiple elements, instead of T* = new T[]
  • std::string for strings instead of char*
  • smart pointers, introduced by the C++11 standard (only for more complex cases) : std::unique_ptr<T> or std::shared_ptr<T>/std::weak_ptr<T>

Note : in your case, mtx is only used inside the main function, so you don't need to allocate it on the heap, you can just write :

int main()
{
    VecStrInt mtx;

    mtx.vstr.push_back("Hello");
    mtx.vint.push_back(1);

    cout << mtx.vint.at(0) << endl;
    cout << mtx.vstr.at(0) << endl;

    return 0;
}

Likewise, you should use std::string instead of char* in VecStrInt, to avoid memory leakage of strings :

#include <string>

struct VecStrInt
{
    vector<string> vstr;
    vector<int> vint;
};
Steakfly
  • 357
  • 3
  • 11