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)
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_back
ed 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
Particle
object 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.
Your code has undefined behavior because
Particle
doesn't have avirtual
destructor.– Praetorian
Aug 31 at 16:10