用默认构造的一个替换堆栈上的现有对象

时间:2018-07-02 10:17:46

标签: c++11 initialization

我想知道最好的/正确的方法来返回对象的初始值,而无需使用delete和new(所有内容都必须保留在堆栈中)

有2个课程:

static const int defaultValue{15};
class Foo
{
  private: 
     int val1{defaultValue};
     short val2{4};
} 
class LongStandingObject
{
   public:
     void resetFoo(int index);
   private:
     Foo foos[100];
}

如果我需要将一些foos重置为其默认值,最好的方法是什么?

  1. Foo

    中创建重置方法
    void Foo::reset()
    {
       val1 = defaultValue;
       val2 = 4;
    }
    

    我真的不喜欢让值来自2个不同的地方,我希望在变量声明旁边的标头中具有默认值。

  2. 替换为本地创建的Foo

    void LongStandingObject::resetFoo(int index)
    {
       foos[index] = Foo();
    }
    

    销毁局部变量时,我会遇到麻烦吗?

  3. 使用memcpy

    void LongStandingObject::resetFoo(int index)
    {
       Foo foo;
       memcpy(foos[index], &foo, sizeof(Foo));
    }
    

    也许可读性不强...

  4. 还有其他方法吗?

2 个答案:

答案 0 :(得分:1)

您的#2很好,而且可能是最清晰的

void LongStandingObject::resetFoo(int index)
{
   foos[index] = Foo();
}

这里没有对象生存期问题:在foos[index]上调用赋值运算符以更改其值以匹配从Foo()实现的临时对象。也就是说,代码完全等同于

{
    Foo tmp;
    foos[index].val1 = tmp.val1;
    foos[index].val2 = tmp.val2;
}

如果启用了优化,几乎所有编译器都可以直接修改foos[index],而无需实际创建临时Foo

如果您确实也想要Foo::reset()函数,则可以使用相同的想法:

void Foo::reset()
{
    *this = Foo();
}

我会避免使用memcpy,因为如果您对Foo进行更改,使该程序不再是可复制的,则该程序将变得不正确。

答案 1 :(得分:0)

您可以做的是在每个变量上使用std :: pair。用variable.first = variable.second = value初始化。之后,每次您要更新设置的变量:variable.second = new_value。当您想还原为原始文件时,请设置:variable.second = variable.first。您可以通过编写宏RestoreDefault(var)来提高代码可读性。

例如:

#define RestoreDefault(var) ((var).second = (var).first)

// int val1{180}; // Instead of this line
std::pair<int,int> val1{ 180,180}; // <- this line

val1.second = 456;
RestoreDefault(val1);

如果您想硬编码阻止以后再重新设置默认值的可能性,请输入:

std::pair<const int,int> val1{ 180,180}; // <- this line

-

添加:数组的相同原理:

class Foo
{
public:
    int x = 100;
    int y = 200;
};

#define RestoreArrDefault(var) ((var).second.fill((var).first))

// Use:

std::pair<Foo, std::array<Foo, 100>> FooAr, FooAr2;

// You can define different arrays with different defaults:
FooAr.first = { 180,360 }; // <- Customize FooAr defaults

// In that point FooAr default is 180,360 and FooAr2 default is 100,200

FooAr.second[3] = { 2,10 }; // <- Edit FooAr index-3 item
RestoreArrDefault(FooAr); // <- Restore Default