在C ++中堆栈对象重新实例化

时间:2010-12-05 04:06:43

标签: c++

我想使用相同的变量,但我想重新实现它。我怎么用c ++做到这一点? 这是一个简单的例子。我尝试重新实例化t1但它不编译。 (注意t1存储在堆栈中。我不是问如何进行动态内存分配)

class Table
{
  private int feet;
  public Table(int x)
  {
    feet=x;
  }
}

Table t1(3);
t1(4);

4 个答案:

答案 0 :(得分:8)

答案是一种称为作业的精彩语言功能。

简而言之,您可以使用=符号更改变量的值 - 甚至是您自己定义的类型的变量。

事实上,你的代码已经在使用赋值,即在构造函数中。

在下面的示例中,我用初始化程序替换了原始代码的赋值,因为初始化程序通常更可取(当没有充分理由使用赋值来初始化成员时选择它们。)

更新t1的值,有效“重用”t1的作业可以是这样的:

class Table
{
private:
    int feet;
public:
    Table( int x ): feet( x ) {}
};

Table t1( 3 );
t1 = Table( 4 );

注1 :可以定义一种类型,以便禁止分配。

注意2 :既然你已经定义了一个转换构造函数,那个接受一个参数,并且因为那个构造函数不是explicit,所以上面的赋值可以更简单地表达(但也许不那么清楚)... ...

t1 = 4;

......结果完全相同。

注3 :你所呈现的代码不会编译,它只是“喜欢”C ++,它不是C ++。我已经修复了错误(我想,但我并不打算通过编译器运行它)。但总的来说,并不总是能够知道甚至猜测所呈现代码中的错误是否与问题有关,所以请复制并粘贴真实代码。

干杯&第h。,

答案 1 :(得分:1)

我建议改用the swap idiom,但如果你真的想在同一个变量中重新创建一个新对象,请使用placement new:

Table t1(3);
t1.~Table();
new (&t1) Table(4);

Placement new只是在你提供的内存中构造一个对象,而不进行任何分配。

如果您决定使用swap,则必须编写交换函数,然后进行重新实现:

Table t1(3);
Table(4).swap(t1);

答案 2 :(得分:0)

为什么要重新注册?那不是RAII。

Instanciation是为了获取对象的空间,然后调用构造函数。如果您只想更改成员值,或者调用某个方法,请创建一些init方法并从构造函数和要重置对象时调用它。这在简单的情况下工作总线并不完全像构造函数。有些事情(比如初始化引用成员)只能在只存在于构造函数中的初始化列表中完成。

显然你应该小心一点,因为在重新分配它们之前应该调用析构函数的成员变量。

Placement new也可以,但它看起来有点过分,你不会通过调用一个简单的方法来重置对象。这很危险,因为它可能导致非常棘手的错误。

如果你继续超载分配操作员轨道,Ben Voight建议的SWAP Idiom可能是你的最佳选择。

我对重新注册的建议是

使用全新实例并将旧实例单独留下会有什么问题?对于不同的任务重用相同的变量对于C来说已经是一个坏主意,因为它使编译器优化更加困难。它仍然是C ++,它也很危险,因为你可能很容易忘记调用第一个对象的析构函数并陷入麻烦。

有些情况下你需要这样做,比如你拿走了对象的地址,并想要改变它的成员。但在这种情况下,最好更改代码以避免这样做。我可以看到没有必要的真实案例。如果有的话,我很想知道。

答案 3 :(得分:0)

首选答案并不能很好地解决问题。 赋值实际上并不重新实现对象,它只是进行赋值。 在示例中,如果feet是const,则解决方案将无法编译。

更棘手的解决方案是使用"Placement new" / "Placement syntax",如:

Table t1(3);
t1.~Table();
new (&t1) Table(4);