C++ - std::unique_ptr in vector is nullptr
Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
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)
c++ polymorphism unique-ptr
add a comment |Â
up vote
7
down vote
favorite
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)
c++ polymorphism unique-ptr
5
Your code has undefined behavior becauseParticle
doesn't have avirtual
destructor.
– Praetorian
Aug 31 at 16:10
2
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
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
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)
c++ polymorphism unique-ptr
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)
c++ polymorphism unique-ptr
asked Aug 31 at 15:46
T0T0R
585
585
5
Your code has undefined behavior becauseParticle
doesn't have avirtual
destructor.
– Praetorian
Aug 31 at 16:10
2
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
add a comment |Â
5
Your code has undefined behavior becauseParticle
doesn't have avirtual
destructor.
– Praetorian
Aug 31 at 16:10
2
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
5
5
Your code has undefined behavior because
Particle
doesn't have a virtual
destructor.– Praetorian
Aug 31 at 16:10
Your code has undefined behavior because
Particle
doesn't have a virtual
destructor.– Praetorian
Aug 31 at 16:10
2
2
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
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
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
19
down vote
accepted
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.
4
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 onParticle
object was nonnullptr
whereas the ones on the inherited types werenullptr
?
– T0T0R
Aug 31 at 15:59
@T0T0R Just a guess, did you setnbParticles
to 1 or 2?
– Brian
Aug 31 at 16:00
1
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
1
@zett42 Usingreserve
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
 |Â
show 5 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
19
down vote
accepted
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.
4
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 onParticle
object was nonnullptr
whereas the ones on the inherited types werenullptr
?
– T0T0R
Aug 31 at 15:59
@T0T0R Just a guess, did you setnbParticles
to 1 or 2?
– Brian
Aug 31 at 16:00
1
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
1
@zett42 Usingreserve
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
 |Â
show 5 more comments
up vote
19
down vote
accepted
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.
4
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 onParticle
object was nonnullptr
whereas the ones on the inherited types werenullptr
?
– T0T0R
Aug 31 at 15:59
@T0T0R Just a guess, did you setnbParticles
to 1 or 2?
– Brian
Aug 31 at 16:00
1
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
1
@zett42 Usingreserve
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
 |Â
show 5 more comments
up vote
19
down vote
accepted
up vote
19
down vote
accepted
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.
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.
edited Aug 31 at 21:08


Justin
12k95091
12k95091
answered Aug 31 at 15:49


Brian
60k791173
60k791173
4
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 onParticle
object was nonnullptr
whereas the ones on the inherited types werenullptr
?
– T0T0R
Aug 31 at 15:59
@T0T0R Just a guess, did you setnbParticles
to 1 or 2?
– Brian
Aug 31 at 16:00
1
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
1
@zett42 Usingreserve
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
 |Â
show 5 more comments
4
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 onParticle
object was nonnullptr
whereas the ones on the inherited types werenullptr
?
– T0T0R
Aug 31 at 15:59
@T0T0R Just a guess, did you setnbParticles
to 1 or 2?
– Brian
Aug 31 at 16:00
1
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
1
@zett42 Usingreserve
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
4
4
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
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
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
@T0T0R Just a guess, did you set
nbParticles
to 1 or 2?– Brian
Aug 31 at 16:00
@T0T0R Just a guess, did you set
nbParticles
to 1 or 2?– Brian
Aug 31 at 16:00
1
1
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
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
1
1
@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
@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
 |Â
show 5 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52118918%2fc-stdunique-ptr-in-vector-is-nullptr%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
5
Your code has undefined behavior because
Particle
doesn't have avirtual
destructor.– Praetorian
Aug 31 at 16:10
2
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