C++ 调用构造函数重新初始化对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2166099/
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 22:21:28  来源:igfitidea点击:

Calling a constructor to re-initialize object

c++constructor

提问by cpx

is it possible to re-initialize an object of a class using its constructor?

是否可以使用其构造函数重新初始化类的对象?

回答by

Sort of. Given a class A:

有点。给定一个 A 类:

A a;
...
a = A();   

the last statement is not initialisation, it is assignment, but it probably does what you want.

最后一条语句不是初始化,它是赋值,但它可能会做你想要的。

回答by AnT

Literally? Yes, by using placement new. But first you have to destruct the previously constructed object.

字面上地?是的,通过使用新的展示位置。但首先你必须破坏先前构造的对象。

SomeClass object(1, 2, 3);
...
object.~SomeClass(); // destruct
new(&object) SomeClass(4, 5, 6); // reconstruct
...
// Final destruction will be done implicitly

The value of this does not go beyond purely theoretical though. Don't do it in practice. The whole thing is ugly beyond description.

尽管如此,它的价值并没有超出纯粹的理论。不要在实践中这样做。整件事丑得无法形容。

回答by R Samuel Klatchko

It's possible, although it's a very bad idea. The reason why is that without calling the destructors on the existing object, you are going to leak resources.

这是可能的,尽管这是一个非常糟糕的主意。原因是,如果不对现有对象调用析构函数,就会泄漏资源。

With that major caveat, if you insist on doing it, you can use placement new.

有了这个主要警告,如果你坚持这样做,你可以使用placement new。

// Construct the class
CLASS cl(args);

// And reconstruct it...
new (&cl) CLASS(args);

回答by denis bider

In C++11, you can do this:

在 C++11 中,你可以这样做:

#include <type_traits>

template <class T, typename... Args>
void Reconstruct(T& x, Args&&... args)
{
    static_assert(!std::has_virtual_destructor<T>::value, "Unsafe"); 
    x.~T();
    new (&x) T(std::forward<Args>(args)...);
}

This allows you to use Reconstructpassing arbitrary constructor parameters to any object. This can avoid having to maintain a bunch of Clearmethods, and bugs that can easily go unnoticed if at some point the object changes, and the Clearmethod no longer matches the constructor.

这允许您使用Reconstruct将任意构造函数参数传递给任何对象。这可以避免必须维护一堆Clear方法,以及如果在某些时候对象发生更改并且Clear方法不再与构造函数匹配时很容易被忽视的错误。

The above will work fine in most contexts, but fail horribly if the reference is to a base within a derived object that has a virtual destructor. For this reason, the above implementation prevents use with objects that have a virtual destructor.

以上在大多数情况下都可以正常工作,但是如果引用是对具有虚拟析构函数的派生对象中的基类的引用,则会失败。出于这个原因,上面的实现阻止使用具有虚拟析构函数的对象。

回答by Dan McGrath

No, constructors are only called when the object is first created. Write a new method to do it instead.

不,只有在第一次创建对象时才会调用构造函数。写一个新方法来代替它。

Edit

编辑

I will not acknowledge placement new, because I don't want to have to get a pet raptor for work.

我不会承认新的安置,因为我不想为了工作而必须得到一只宠物猛禽。

See this comic, but think of the topic on hand...

看到这个漫画,但想想手头的话题......

回答by JaredPar

Short answer:

简短的回答:

No. If part of your object's intended behavior is to be initialized several times, then the best way to implement this is through an accessible initialization method. The constructor of your class can simply defer to this method.

不可以。如果您的对象预期行为的一部分要被初始化多次,那么实现这一点的最佳方法是通过一个可访问的初始化方法。您的类的构造函数可以简单地遵循此方法。

class C1 {
public:
  C1(int p1, int p2) {
    Init(p1,p2);
  }
  void Init(int p1, int p2) { ... }
};

Nitpicker corner:

挑剔角:

Is there some incredibly evil way to call a constructor in C++ after an object is created? Almost certainly, this is C++ after all. But it's fundamentally evil and it's behavior is almost certainly not defined by the standard and should be avoided.

在创建对象后,是否有一些非常邪恶的方法可以在 C++ 中调用构造函数?几乎可以肯定,这毕竟是 C++。但它从根本上是邪恶的,它的行为几乎肯定没有由标准定义,应该避免。

回答by Martin York

Yes you can cheat and use placement new.
Note: I do not advice this:

是的,您可以作弊并使用新放置。
注意:我不建议这样做:

#include <new>

reInitAnA(A& value)
{
    value.~A();            // destroy the old one first.
    new (&value) A();      // Call the constructor 
                           // uses placement new to construct the new object
                           // in the old values location.
}

回答by Coyl

I usually write the following in modern C++ :

我通常用现代 C++ 编写以下内容:

SomeClass a;
...
a = decltype(a)();

It may be not the most effective way, as it effectively constructs another object of the same type of aand assigns it to a, but it works in most cases, you don't have to remember the type of a, and it adapts if the type changes.

它可能不是最有效的方法,因为它有效地构造了另一个相同类型的对象a并将其分配给a,但它在大多数情况下都有效,您不必记住 的类型a,并且如果类型发生变化它会适应.

回答by Jagannath

Instead of destructing and reinitializing as suggested by some of the answers above, it's better to do an assignment like below. The code below is exception safe.

与其按照上面的一些答案所建议的那样进行破坏和重新初始化,不如进行如下作业。下面的代码是异常安全的。

    T& reinitialize(int x, int y)
    {
        T other(x, y);
        Swap(other); // this can't throw.
        return *this;
    }

回答by UncleBens

May-be not what you have in mind, but since you didn't mention what it is for, I suppose one answer would be that you'd do it by controlling scope and program flow.

可能不是您的想法,但由于您没有提到它的用途,我想一个答案是您可以通过控制范围和程序流程来做到这一点。

For example, you wouldn't write a game like this:

例如,您不会编写这样的游戏:

initialize player
code for level 1
...
reinitialize player
code for level 2
...
etc

Instead you'd strive for:

相反,你会努力:

void play_level(level_number, level_data) {
    Player player; //gets "re-initialized" at the beginning of each level using constructor
    //code for level
}

void game() {
    level_number = 1;
    while (some_condition) {
        play_level(level_number, level_data);
        ++level_number;
    }
 }

(Very rough outline to convey the idea, not meant to be remotely compilable.)

(传达想法的非常粗略的轮廓,并不意味着可以远程编译。)