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

The name of the pictureThe name of the pictureThe name of the pictureClash 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)






share|improve this question
















  • 5




    Your code has undefined behavior because Particle doesn't have a virtual 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















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)






share|improve this question
















  • 5




    Your code has undefined behavior because Particle doesn't have a virtual 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













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)






share|improve this question













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)








share|improve this question











share|improve this question




share|improve this question










asked Aug 31 at 15:46









T0T0R

585




585







  • 5




    Your code has undefined behavior because Particle doesn't have a virtual 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




    Your code has undefined behavior because Particle doesn't have a virtual 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













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_backed additional elements to it instead of assigning to the existing elements. Fix this by removing the (nbParticles) from the vector initialization.






share|improve this answer


















  • 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 on Particleobject 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






  • 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 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











Your Answer





StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















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






























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_backed additional elements to it instead of assigning to the existing elements. Fix this by removing the (nbParticles) from the vector initialization.






share|improve this answer


















  • 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 on Particleobject 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






  • 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 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















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_backed additional elements to it instead of assigning to the existing elements. Fix this by removing the (nbParticles) from the vector initialization.






share|improve this answer


















  • 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 on Particleobject 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






  • 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 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













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_backed additional elements to it instead of assigning to the existing elements. Fix this by removing the (nbParticles) from the vector initialization.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








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 on Particleobject 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






  • 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 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













  • 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 on Particleobject 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






  • 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 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








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 Particleobject 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 Particleobject 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


















 

draft saved


draft discarded















































 


draft saved


draft discarded














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













































































Comments

Popular posts from this blog

What does second last employer means? [closed]

List of Gilmore Girls characters

One-line joke