堆栈对象的延迟初始化

Lazy initialization for stack objects?

本文关键字:初始化 延迟 对象 堆栈      更新时间:2023-10-16

我知道我们可以对堆对象执行以下操作:

/* Heap objects */
Pet *pet;
if (...)
    pet = new Pet("Dog");
else
    pet = new Pet("Cat");    

但是,如果我们想在堆栈上声明Pet对象,我们该怎么做呢?

/* Stack objects */
Pet pet;
if (...)
    -?-
else
    -?-

尝试以下

Pet pet(theCondition ? "Dog" : "Cat");

或者,如果条件块比单个初始化存储更复杂,则将用于初始化的const char*存储为单独的本地

const char* pArgument;
if (...) {
  ...
  pArgument = "Dog";
} else {
  ...
  pArgument = "Cat";
}
Pet pet(pArgument);
string param;
if (...)
   param = "Dog"
else 
   param = "Cat";
Pet pet(param);

延迟初始化显然需要由基础对象本身完成。

if (...)
    animal.Initialize("Dog");
else
    animal.Initialize("Cat");

如果对象具有需要由派生类填充的虚拟方法,那么这是不起作用的——在这种情况下,指针是唯一可行的解决方案。

如果您的类支持默认构造和复制赋值,则以下操作将起作用:

Pet pet;  //- assumes Pet class supports default construction.
if (theCondition)
{
    pet = Pet("Dog");  //- assumes Pet class supports copy assignment.
}
else
{
    pet = Pet("Cat");
}

当然,你必须为两个结构和一个副本付费,才能将你的宠物放在堆栈上。

boost::optional可用于获得延迟初始化(即使是容器):

boost::optional<Animal> d;
if(foo) d = Animal("Dog"); 

我认为堆栈对象不能有同样的东西。

然而,这里有一些替代方案:

/* Stack objects */
if (...)
{
  Animal animal("Cat");
  ...
}
else
{
  Animal animal("Dog");
  ...
}

或者不那么懒惰

Animal cat("Cat");
Animal dog("Dog");
Animal *animal;
if (...)
{
  animal = &cat;
}
else
{
  animal = &dog;
}

还有一个选项是使用函数,或者在C++11中,lambdas:

auto returnArg = [&]() -> const char * {
    if (...) return "Dog";
    else return "Cat";
};
Animal animal(returnArg());

将堆栈的加载分成两个步骤。

void doTheThingToTheAnimal(Animal& animal) {
  ...
}

// select the animal
if (...) {
  Animal animal("Dog");
  doTheThingToTheAnimal(animal);
} else {
  Animal animal("Cat");
  doTheThingToTheAnimal(animal); 
}