RandomUser
RandomUser

Reputation: 4220

Storing references with std:: containers , gnu c++98

I came across this comment in another SO post, regarding storing references in a std container:

It's a flaw in the C++ language. You can't take the address of a reference, since attempting to do so would result in the address of the object being referred to, and thus you can never get a pointer to a reference. std::vector works with pointers to its elements, so the values being stored need to be able to be pointed to. You'll have to use pointers instead.

The post:

Why can't I make a vector of references?

Assuming this is correct, can someone explain why my below code works? I'm not trying to imply the person is wrong, I'm just trying to make sure I understand what's possible and what's not.

My code:

#include <iostream>
#include <vector>
#include "stdio.h"

struct TestStruct
{
    int x;
    int y;
};

class TestClass {
public:
TestClass(int x, int y);
int getX();
int getY();
private:
int mX;
int mY;
};

TestClass::TestClass(int x, int y)
{
    mX = x;
    mY = y;
}

int TestClass::getX()
{
    return mX;
}

int TestClass::getY()
{
    return mY;
}


int main()
{
    // test struct
    std::vector<TestStruct> structVec;

    TestStruct testStruct;
    testStruct.x = 10;
    testStruct.y = 100;
    structVec.push_back(testStruct);
    testStruct.x = 2;
    testStruct.y = 200;
    structVec.push_back(testStruct);
    testStruct.x = 3;
    testStruct.y = 300;
    structVec.push_back(testStruct);

    for (int i = 0; i < structVec.size(); i++)
    {
        printf("testStruct [%d] - [x: %d, y: %d] \n", i, structVec[i].x, structVec[i].y);
    }

    // test object
    std::vector<TestClass> objVec;

    objVec.push_back(*new TestClass(10, 100));
    objVec.push_back(*new TestClass(20, 200));
    objVec.push_back(*new TestClass(30, 300));
    for (int i = 0; i < objVec.size(); i++)
    {
        printf("objVec [%d] - [x: %d, y: %d] \n", i, objVec[i].getX(), objVec[i].getY());
    }
}

Output:

testStruct [0] - [x: 10, y: 100] 
testStruct [1] - [x: 2, y: 200] 
testStruct [2] - [x: 3, y: 300] 
objVec [0] - [x: 10, y: 100] 
objVec [1] - [x: 20, y: 200] 
objVec [2] - [x: 30, y: 300] 

Upvotes: 1

Views: 92

Answers (1)

Mr.C64
Mr.C64

Reputation: 43044

When you write code like this:

objVec.push_back(*new TestClass(10, 100));

you are creating a new instance of TestClass on the heap, then you are dereferencing it using *, and then this is copied inside the vector when you call push_back.

But you are leaking the original TestClass object allocated using new on the heap.

You may want to use a vector<shared_ptr<TestClass>> or vector<unique_ptr<TestClass>> instead if you want to store pointers (smart pointers) instead of TestClass instances (are you sure?).

Note that a vector of references would be vector<TestClass&>, which is wrong.

P.S. As you cited C++98" in the title, you can't have unique_ptr as it requires C++11 move semantics. shared_ptr became standard with C++11; you can still use boost::shared_ptr in C++98.

Upvotes: 1

Related Questions