Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ - std::unique_ptr in vector<> is nullptr

I want to store Particle objects in a vector object, so I can access it later. These particles (Electrons and Protons) are inherited from the Particle class which contains a toString() virtual method. This toString() method is then overrided in Electron and Proton classes.

When I read the vector container, I want to access to the toString() method specific to Electron or Proton, and not to Particle.

Apparently, one way is to use std::unique_ptr. Here is the part of the code I try to run:

int main(){
    /**/
    std::vector<std::unique_ptr<Particle>> particles(nbParticles);

    particles.push_back(std::unique_ptr<Electron>( new Electron(1.0, 2.0, 3.0)));
    particles.push_back(std::unique_ptr<Proton>(new Proton(1.0, 2.0, 3.0)));
    particles.push_back(std::unique_ptr<Particle>(new Particle(0.0, 0.0, 1.0, 2.0, 3.0)));

    if (particles[0]==nullptr){
        std::cout<< "index=0 : nullptr"<<std::endl; //There is a null_ptr at particles[0]
    }

    if (particles[2]==nullptr){
        std::cout<< "index=2 : nullptr"<<std::endl; //There is not a null_ptr at particles[2]
    }

    std::cout<<particles[0]->toString()<<std::endl; //This is what I'm trying to do
    /**/
}

A pointer to a Particle object seems to be fine, but not to an Electron or Proton. I guess there is something wrong with the constructors ?

class Particle
{
public:
    Particle();
    Particle(double mass, double charge, double posX, double posY, double posZ);
    virtual std::string toString() const;
}

class Electron : public Particle
{
public:
    Electron(double PosX, double PosY, double PosZ);
    virtual std::string toString() const;
}

class Proton : public Particle
{
public:
    Proton(double PosX, double PosY, double PosZ);
    virtual std::string toString() const;
}

and the definitions:

Particle::Particle(double mass, double charge, double posX, double posY, double posZ) :
    m_mass(mass), m_charge(charge),
    m_posX(posX), m_posY(posY), m_posZ(posZ) {}


Electron::Electron(double PosX, double PosY, double PosZ) :
    Particle(9.109E-31, -1.602E-19, PosX, PosY, PosZ){}

Proton::Proton(double PosX, double PosY, double PosZ) :
    Particle(9.109E-31, +1.602E-19, PosX, PosY, PosZ){}
like image 395
T0T0R Avatar asked Aug 31 '18 15:08

T0T0R


People also ask

Can you set unique_ptr to Nullptr?

It will work. unique_ptr& operator=(nullptr_t) noexcept ; Effects: reset() .

What is a unique_ptr in C++?

> class unique_ptr<T[], Deleter>; (2) (since C++11) std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope.

What is the default value of unique_ptr?

std::unique_ptr::unique_ptr default constructor (1), and (2) The object is empty (owns nothing), with value-initialized stored pointer and stored deleter.

Is unique_ptr null after move?

Yes, you can compare it to nullptr after the move and it is guaranteed to compare equal. This is clearly true after calling release().


1 Answers

You've made a classic mistake that trips up even the most experienced C++ programmers: you declared the vector with an initial size and then push_backed additional elements to it instead of assigning to the existing elements. Fix this by removing the (nbParticles) from the vector initialization.

like image 120
Brian Bi Avatar answered Oct 27 '22 01:10

Brian Bi