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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/800368/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:20:31  来源:igfitidea点击:

Declaring an object before initializing it in c++

c++scopedeclarationinstantiation

提问by Quantum7

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

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

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

Basially, I just want to declare a outside of the conditional so it gets the right scope.

基本上,我只想在条件之外声明一个,以便它获得正确的范围。

Is there any way to do this without using pointers and allocating aon the heap? Maybe something clever with references?

有没有办法在不使用指针和a在堆上分配的情况下做到这一点?也许有一些聪明的参考?

采纳答案by Uri

You can't do this directly in C++ since the object is constructed when you define it with the default constructor.

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

You could, however, run a parameterized constructor to begin with:

但是,您可以首先运行参数化构造函数:

Animal a(getAppropriateString());

Or you could actually use something like the ?: operatorto determine the correct string. (Update: @Greg gave the syntax for this. See that answer)

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

回答by Greg Hewgill

You can't declare a variable without calling a constructor. However, in your example you could do the following:

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

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

回答by joce

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:

1-使用指针:

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

// ...
delete a;

2- Add an Init method to Animal:

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" );

I'd personally go with option 2.

我个人会选择选项 2。

回答by Steve Fallows

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

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

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.

我建议这样做是因为我曾在禁止使用条件运算符的地方工作过。(叹气!)此外,这可以很容易地扩展到两种选择之外。

回答by paquetp

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

回答by Logan Capaldo

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

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

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:

(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

回答by rkadeFR

The best work around is to use pointer.

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

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

回答by RodolfoAP

You can also use std::move:

您还可以使用 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);
        }
...

回答by DeadHead

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 时,您仍然必须调用构造函数,无论它是一个什么都不做的构造函数,还是仍然将值初始化为任何值。因此,此方法创建两个对象,一个在初始化时,另一个在 if 语句中。

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

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

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

This way would be more efficient.

这种方式会更有效率。