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

时间:2009-04-29 00:16:52

标签: c++ scope declaration instantiation

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

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

基本上,我只是想声明条件的外部,以便它获得正确的范围。

有没有办法在不使用指针并在堆上分配a的情况下执行此操作?也许引用聪明的东西?

10 个答案:

答案 0 :(得分:40)

如果不调用构造函数,则无法声明变量。但是,在您的示例中,您可以执行以下操作:

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

答案 1 :(得分:33)

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

但是,您可以运行参数化构造函数来开始:

Animal a(getAppropriateString());

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

答案 2 :(得分:18)

你不能在这里使用引用,因为只要你离开作用域,引用就会指向一个将被删除的对象。

真的,你有两个选择:

1-使用指针:

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

// ...
delete a;

2-将Init方法添加到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。

答案 3 :(得分:16)

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

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

我建议这是因为我曾经禁止使用条件运算符的地方。 (叹气!)此外,这可以很容易地扩展到两个替代方案之外。

答案 4 :(得分: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.

如果你还想使用。语法而不是 - &gt;,您可以在上面的代码之后执行此操作:

Animal& a = *p_a;

// do stuff with a. whatever

答案 5 :(得分: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

答案 6 :(得分:1)

最好的解决方法是使用指针。

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

答案 7 :(得分:1)

自c ++ 17起,现在有一种无开销的方式来执行此操作:std::optional。在这种情况下,代码为:

#include <optional>

std::optional<Animal> a;
if(happyDay()) 
    a.emplace("puppies");
else
    a.emplace("toads");

答案 8 :(得分:0)

您也可以使用std :: move:

let data = [
  { id: 1, attribute: "A" },
  { id: 2, attribute: "b" },
  { id: 3, attribute: "C" },
  { id: 4, attribute: "A" },
  { id: 5, attribute: "e" },
  { id: 6, attribute: "C" },
  { id: 7, attribute: "g" },
  { id: 8, attribute: "h" },
  { id: 9, attribute: "A" }
];

let result = [
  [1, 4, 9],
  [3, 6]
];

答案 9 :(得分:-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" );

这种方式会更有效率。