在c ++中初始化之前声明一个对象

问题描述 投票:49回答:9

是否可以在c ++中声明变量而不实例化它?我想做这样的事情:

Animal a;
if( happyDay() ) 
    a( "puppies" ); //constructor call
else
    a( "toads" );

很容易,我只想声明条件的外部,以便获得正确的范围。

是否有任何方法可以在不使用指针的情况下并且在堆上分配a?也许有些巧妙的参考文献?

c++ scope declaration instantiation
9个回答
34
投票

您无法使用C ++直接执行此操作,因为使用默认构造函数定义对象时便会构造该对象。

但是,您可以运行参数化的构造函数,以以下内容开头:

Animal a(getAppropriateString());

或者您实际上可以使用类似?: operator的东西来确定正确的字符串。(更新:@Greg为此提供了语法。请参见该答案)


41
投票

您必须在不调用构造函数的情况下声明变量。但是,在您的示例中,您可以执行以下操作:

Animal a(happyDay() ? "puppies" : "toads");

25
投票

您不能在这里使用引用,因为一旦超出范围,引用将指向将被删除的对象。

真的,您在这里有两个选择:

1-使用指针:

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

// ...
delete a;

2-将初始化方法添加到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" );

我个人选择选项2。


16
投票

我更喜欢格雷格的答案,但您也可以这样做:

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

我建议这样做,因为我在禁止条件运算符的地方工作。 (叹气!)此外,可以很容易地将其扩展到两个替代方案之外。


7
投票

如果要避免垃圾回收,可以使用智能指针。

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.

如果您仍然想使用。语法而不是->,您可以在上面的代码之后执行此操作:

Animal& a = *p_a;

// do stuff with a. whatever

6
投票

除了Greg Hewgill的答案,还有其他一些选择:

将代码主体放入函数中:

void body(Animal & a) {
    ...
}

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

((Ab)使用新的展示位置:

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

1
投票

最佳解决方法是使用指针。

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

0
投票

您也可以使用std :: move:

class Ball {
private:
        // This is initialized, but not as needed
        sf::Sprite ball;
public:
        Ball() {
                texture.loadFromFile("ball.png");
                // This is a local object, not the same as the class member.
                sf::Sprite ball2(texture);
                // move it
                this->ball=std::move(ball2);
        }
...

-4
投票

是,您可以执行以下操作:

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

将正确调用构造函数。

编辑:忘记了一件事...声明a时,您必须仍然调用构造函数,无论它是什么都不做的构造函数,还是仍然将值初始化为任何值。因此,此方法创建两个对象,一个在初始化时,一个在if语句中。

一种更好的方法是创建类的init()函数,例如:

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

这种方式会更有效率。

© www.soinside.com 2019 - 2024. All rights reserved.