是否可以在不实例化的情况下在c ++中声明变量?我想做这样的事情:
Animal a;
if( happyDay() )
a( "puppies" ); //constructor call
else
a( "toads" );
基本上,我只是想声明条件的外部,以便它获得正确的范围。
有没有办法在不使用指针并在堆上分配a
的情况下执行此操作?也许引用聪明的东西?
答案 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" );
这种方式会更有效率。