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

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.


Particle


vector


Electrons


Protons


Particle


toString()


toString()


Electron


Proton



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


toString()


Electron


Proton


Particle



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


std::unique_ptr


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 ?


Particle


Electron


Proton


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)





Your code has undefined behavior because Particle doesn't have a virtual destructor.
– Praetorian
Aug 31 at 16:10


Particle


virtual





If T is a derived class of some base B, then std::unique_ptr<T> is implicitly convertible to std::unique_ptr<B>. The default deleter of the resulting std::unique_ptr<B> will use operator delete for B, leading to undefined behavior unless the destructor of B is virtual. link (under Notes)
– asynts
Aug 31 at 17:16





1 Answer
1



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.


push_back


(nbParticles)





Might want to add they should add a call to reserve if the know ow many elements there will be. That way they don't have to g through multiple reallocations.
– NathanOliver
Aug 31 at 15:59





Thank you, it works now :) But why the pointer on Particleobject was non nullptr whereas the ones on the inherited types were nullptr?
– T0T0R
Aug 31 at 15:59



Particle


nullptr


nullptr





@T0T0R Just a guess, did you set nbParticles to 1 or 2?
– Brian
Aug 31 at 16:00


nbParticles





To be precise, it was int nbElectrons1; int nbProtons1; std::vector<std::unique_ptr<Particle>> particles(nbElectrons+nbProtons); so yes
– T0T0R
Aug 31 at 16:02






@zett42 Using reserve when you know the size is absolutely not premature optimization. Premature optimization is harming the readability / maintainability of the code or increasing the complexity of the code to make code run faster without measuring that it's needed. particles.reserve(3); improves the readability / maintainability of the code - it clearly communicates, "I know the size of this vector beforehand". Without it, the code communicates an uncertainty about what size the vector will be.
– Justin
Aug 31 at 21:04



reserve


particles.reserve(3);



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)