简体   繁体   中英

What's the difference between these two classes?

Below, I'm not declaring my_ints as a pointer. I don't know where the memory will be allocated. Please educate me here!

#include <iostream>
#include <vector>

class FieldStorage
{
private:
    std::vector<int> my_ints;

public:
    FieldStorage()
    {
        my_ints.push_back(1);
        my_ints.push_back(2);
    }

    void displayAll()
    {
        for (int i = 0; i < my_ints.size(); i++)
        {
            std::cout << my_ints[i] << std::endl;
        }
    }
};

And in here, I'm declaring the field my_ints as a pointer:

#include <iostream>
#include <vector>

class FieldStorage
{
private:
    std::vector<int> *my_ints;

public:
    FieldStorage()
    {
        my_ints = new std::vector<int>();
        my_ints->push_back(1);
        my_ints->push_back(2);
    }

    void displayAll()
    {
        for (int i = 0; i < my_ints->size(); i++)
        {
            std::cout << (*my_ints)[i] << std::endl;
        }
    }

    ~FieldStorage()
    {
        delete my_ints;
    }
};

main() function to test:

int main()
{
    FieldStorage obj;
    obj.displayAll();
    return 0;
}

Both of them produces the same result. What's the difference?

In terms of memory management, these two classes are virtually identical. Several other responders have suggested that there is a difference between the two in that one is allocating storage on the stack and other on the heap, but that's not necessarily true, and even in the cases where it is true, it's terribly misleading. In reality, all that's different is where the metadata for the vector is allocated; the actual underlying storage in the vector is allocated from the heap regardless.

It's a little bit tricky to see this because you're using std::vector , so the specific implementation details are hidden. But basically, std::vector is implemented like this:

template <class T>
class vector {
public:
    vector() : mCapacity(0), mSize(0), mData(0) { }
    ~vector() { if (mData) delete[] mData; }
    ...
protected:
    int mCapacity;
    int mSize;
    T *mData;
};

As you can see, the vector class itself only has a few members -- capacity, size and a pointer to a dynamically allocated block of memory that will store the actual contents of the vector.

In your example, the only difference is where the storage for those few fields comes from. In the first example, the storage is allocated from whatever storage you use for your containing class -- if it is heap allocated, so too will be those few bits of the vector . If your container is stack allocated, so too will be those few bits of the vector .

In the second example, those bits of the vector are always heap allocated.

In both examples, the actual meat of the vector -- the contents of it -- are allocated from the heap, and you cannot change that.

Everybody else has pointed out already that you have a memory leak in your second example, and that is also true. Make sure to delete the vector in the destructor of your container class.

You have to release ( to prevent memory leak ) memory allocated for vector in the second case in the FieldStorage destructor.

FieldStorage::~FieldStorage()
{
    delete my_ints;
}

As Mykola Golubyev pointed out, you need to delete the vector in the second case.

The first will possibly build faster code, as the optimiser knows the full size of FieldStorage including the vector, and could allocate enough memory in one allocation for both.

Your second implementation requires two separate allocations to construct the object.

I think you are really looking for the difference between the Stack and the Heap .

The first one is allocated on the stack while the second one is allocated on the heap.

In the first example, the object is allocated on the stack.

The the second example, the object is allocated in the heap, and a pointer to that memory is stored on the stack.

第一种方式是使用的优先方法,你不需要向量上的指针,忘记删除它。

the difference is that the second allocates the vector dynamically. there are few differences:

  • you have to release memory occupied by the vector object (the vector object itself, not the object kept in the vector because it is handled correctly by the vector). you should use some smart pointer to keep the vector or make (for example in the destructor):

    delete my_ints;

  • the first one is probably more efficient because the object is allocated on the stack.

  • access to the vector's method have different syntax :)

The first version of FieldStorage contains a vector. The size of the FieldStorage class includes enough bytes to hold a vector. When you construct a FieldStorage, the vector is constructed right before the body of FieldStorage's constructor is executed. When a FieldStorage is destructed, so is the vector.

This does not necessarily allocate the vector on the stack; if you heap-allocate a FieldStorage object, then the space for the vector comes from that heap allocation, not the stack. If you define a global FieldStorage object, then the space for the vector comes from neither the stack nor the heap, but rather from space designated for global objects (eg the .data or .bss section on some platforms).

Note that the vector performs heap allocations to hold the actual data, so it is likely to only contain a few pointers, or a pointer and couple of lengths, but it may contain whatever your compiler's STL implementation needs it to.

The second version of FieldStorage contains a pointer to a vector. The size of the FieldStorage class includes room for a pointer to a vector, not an actual vector. You are allocating storage for the vector using new in the body of FieldStorage's constructor, and you leaking that storage when FieldStorage is destructed, because you didn't define a destructor that deletes the vector.

In the first case, the std::vector is being put directly into your class (and it is handling any memory allocation and deallocation it needs to grow and shrink the vector and free the memory when your object is destroyed; it is abstracting the memory management from you so that you don't have to deal with it). In the second case, you are explicitly allocating the storage for the std::vector in the heap somewhere, and forgetting to ever delete it, so your program will leak memory.

The size of the object is going to be different. In the second case the Vector<>* only takes up the size of a pointer (4bytes on 32bit machines). In the first case, your object will be larger.

One practical difference is that in your second example, you never release either the memory for the vector, or its contents (because you don't delete it, and therefore call its destructor).

But the first example will automatically destroy the vector (and free its contents) upon destruction of your FieldStorage object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM