使用new(this)重用构造函数

Bra*_*nar 19 c++ this placement-new

最近出现在我作为助教的课堂上.我们正在教学生如何用c ++编写复制构造函数,最初教过java的学生问你是否可以从另一个构建函数调用.我知道这个问题的答案是否定的,因为他们在课堂上使用了迂腐的旗帜作为他们的代码,而旧标准对此并不支持.我在Stackoverflow和其他网站上发现了使用new (this)如下伪造此内容的建议

class MyClass
{
    private:
        int * storedValue;
    public:
        MyClass(int initialValue = 0)
        {
            storedValue = new int(initialValue);
        }

        ~ MyClass()
        {
            delete storedValue;
        }

        MyClass(const MyClass &b)
        {
            new (this) MyClass(*(b.storedValue));
        }

        int value() {
            return *storedValue;
        }
};
Run Code Online (Sandbox Code Playgroud)

这是非常简单的代码,显然不会通过重用构造函数来保存任何代码,但它仅仅是例如.

我的问题是,这是否符合标准,如果有任何边缘情况应该考虑,以防止这是声音代码?

编辑:我应该注意到这对我来说似乎是非常危险的,但是从我不太了解它不仅仅是知道如何变坏它的观点来看更多.我只是想确保如果学生被问到我可以指导他们为什么能够或不应该这样做.为了所有实际目的,我已经向他们建议使用共享初始化方法.这更像是一个教学问题,而不是一个实际项目.

ton*_*ony 17

C++ 0x将引入语法以允许构造函数调用其他构造函数.

在那之前,new(this)某些情况下有效,但不是全部.特别是,一旦在构造函数中,您的基类已经完全构造.重构通过new(this)重新调用基础构造函数而不调用基础析构函数,所以如果基类没有期待这种hackery,那么期待问题 - 而且它们可能不是.

清晰的一个例子:

class Base
{
public:
   char *ptr;
   MyFile file;
   std::vector vect;
   Base()
   {
       ptr = new char[1000];
       file.open("some_file");
   }
   ~Base()
   {
       delete [] ptr;
       file.close();
   }
};

class Derived : Base
{
    Derived(Foo foo)
    {
    }
    Derived(Bar bar)
    {
       printf(ptr...);  // ptr in base is already valid
       new (this) Derived(bar.foo); // ptr re-allocated, original not deleted
       //Base.file opened twice, not closed
       // vect is who-knows-what
       // etc
    }
}
Run Code Online (Sandbox Code Playgroud)

或者他们说'欢闹随之而来'


Mik*_*our 11

成员和基类将在进入构造函数体之前初始化,然后在调用第二个构造函数时再次初始化.通常,这将导致内存泄漏并可能导致未定义的行为.

所以答案是"不,这不是声音代码".


Nat*_*ate 5

以下是C++常见问题解答中的问题,在一个问题中,"类的一个构造函数可以调用同一个类的另一个构造函数来初始化这个对象吗?":

BTW不要试图通过新的安置来实现这一点.有些人认为他们可以new(this) Foo(x, int(x)+7)在体内说出来Foo::Foo(char).然而,这是坏的,坏的,坏的.请不要写信告诉我,它似乎适用于您特定版本的特定编译器; 这不好.构造函数在幕后做了一堆小小的神奇事情,但是那些不好的技术会在那些部分构造的位上进行.拒绝吧.