Declaring an object before initializing it in c++

前端 未结 10 2193
你的背包
你的背包 2020-12-13 17:17

Is it possible to declare a variable in c++ without instantiating it? I want to do something like this:

Animal a;
if( happyDay() ) 
    a( \"puppies\" ); //c         


        
相关标签:
10条回答
  • 2020-12-13 17:24

    Since c++17, there is now an overhead-free way to do this: std::optional. The code in this case would be:

    #include <optional>
    
    std::optional<Animal> a;
    if(happyDay()) 
        a.emplace("puppies");
    else
        a.emplace("toads");
    
    0 讨论(0)
  • 2020-12-13 17:27

    In addition to Greg Hewgill's answer, there are a few other options:

    Lift out the main body of the code into a function:

    void body(Animal & a) {
        ...
    }
    
    if( happyDay() ) {
      Animal a("puppies");
      body( a );
    } else {
      Animal a("toad");
      body( a );
    }
    

    (Ab)Use placement new:

    struct AnimalDtor {
       void *m_a;
       AnimalDtor(void *a) : m_a(a) {}
       ~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
    };
    
    char animal_buf[sizeof(Animal)]; // still stack allocated
    
    if( happyDay() )
      new (animal_buf) Animal("puppies");
    else
      new (animal_buf) Animal("toad");
    
    AnimalDtor dtor(animal_buf); // make sure the dtor still gets called
    
    Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
    ... // carry on
    
    0 讨论(0)
  • 2020-12-13 17:28

    I prefer Greg's answer, but you could also do this:

    char *AnimalType;
    if( happyDay() ) 
        AnimalType = "puppies";
    else
        AnimalType = "toads";
    Animal a(AnimalType);
    

    I suggest this because I've worked places where the conditional operator was forbidden. (Sigh!) Also, this can be expanded beyond two alternatives very easily.

    0 讨论(0)
  • 2020-12-13 17:35

    If you want to avoid garbage collection - you could use a smart pointer.

    auto_ptr<Animal> p_a;
    if ( happyDay() )
        p_a.reset(new Animal( "puppies" ) );
    else
        p_a.reset(new Animal( "toads" ) );
    
    // do stuff with p_a-> whatever.  When p_a goes out of scope, it's deleted.
    

    If you still want to use the . syntax instead of ->, you can do this after the code above:

    Animal& a = *p_a;
    
    // do stuff with a. whatever
    
    0 讨论(0)
  • 2020-12-13 17:37

    You can't use references here, since as soon as you'd get out of the scope, the reference would point to a object that would be deleted.

    Really, you have two choices here:

    1- Go with pointers:

    Animal* a;
    if( happyDay() ) 
        a = new Animal( "puppies" ); //constructor call
    else
        a = new Animal( "toads" );
    
    // ...
    delete a;
    

    2- Add an Init method to Animal:

    class Animal 
    {
    public:
        Animal(){}
        void Init( const std::string& type )
        {
            m_type = type;
        }
    private:
        std:string m_type;
    };
    
    Animal a;
    if( happyDay() ) 
        a.Init( "puppies" );
    else
        a.Init( "toads" );
    

    I'd personally go with option 2.

    0 讨论(0)
  • 2020-12-13 17:40

    Yes, you can do do the following:

    Animal a;
    if( happyDay() )
        a = Animal( "puppies" );
    else
        a = Animal( "toads" );
    

    That will call the constructors properly.

    EDIT: Forgot one thing... When declaring a, you'll have to call a constructor still, whether it be a constructor that does nothing, or still initializes the values to whatever. This method therefore creates two objects, one at initialization and the one inside the if statement.

    A better way would be to create an init() function of the class, such as:

    Animal a;
    if( happyDay() )
        a.init( "puppies" );
    else
        a.init( "toads" );
    

    This way would be more efficient.

    0 讨论(0)
提交回复
热议问题