简体   繁体   English

为什么 C++ 构造函数必须对数组使用动态分配?

[英]Why must C++ constructor use dynamic allocation for array?

In my course notes these two examples are given.在我的课程笔记中给出了这两个例子。 Apparently the first one is not allowed, is there a technical reason why I can't allocate on stack?显然第一个是不允许的,我不能在堆栈上分配是否有技术原因? Or is this the C++ standard?还是这是 C++ 标准?

   // Constructor may force dynamic allocation when initializating an array of objects.

   Complex ac[10];             // complex array initialized to 0.0
    for ( int i = 0; i < 10; i += 1 ) {
         ac[i] = (Complex){ i, 2.0 } // disallowed
    }


    // MUST USE DYNAMIC ALLOCATION
    Complex *ap[10];            // array of complex pointers
    for ( int i = 0; i < 10; i += 1 ) {
         ap[i] = new Complex( i, 2.0 ); // allowed
    }

The first one is not valid syntax.第一个不是有效的语法。 But assuming your Complex class has a public copy-assignment operator (the implicit one should probably be fine), then the following should be fine:但是假设您的Complex class 有一个公共的复制赋值运算符(隐式的应该没问题),那么以下应该没问题:

Complex ac[10];             // complex array initialized to 0.0
for ( int i = 0; i < 10; i += 1 ) {
     ac[i] = Complex( i, 2.0 );
}

Apparently the first one is not allowed显然第一个是不允许的

True, but only because it uses a wrong syntax.没错,但这只是因为它使用了错误的语法。 The following works:以下作品:

ac[i] = Complex(i, 2.0);

So the claim is in fact wrong (assuming that Complex can be assigned to, which it by default can) – no dynamic allocation is needed.所以这个说法实际上是错误的(假设Complex可以被分配,默认情况下它可以)——不需要动态分配。

The following is perfectly allowed -- you just had the wrong syntax.以下是完全允许的——你只是有错误的语法。 You can't cast initializer lists, but you can call constructors as though they are functions.您不能强制转换初始值设定项列表,但您可以调用构造函数,就好像它们是函数一样。

Complex ac[10];  // calls default constructor for each element
for ( int i = 0; i < 10; i += 1 ) {
     ac[i] = Complex(i, 2.0);  // constructs a temporary,
                               // then uses the assignment operator
}

You may of course provide all the values in an initializer-list, like您当然可以在初始化列表中提供所有值,例如

Complex ac[] = { Complex(0, 2.0), Complex(1, 2.0), /* and so on */ };

but this gets very unwieldy very quickly as the size increases.但是随着尺寸的增加,这会很快变得非常笨拙。 So it's natural to want to use a loop.所以很自然地想要使用循环。

While it's not impossible to independently initialize elements in an automatic (which usually equates to "on stack") buffer, it's not at all easy.虽然在自动(通常等同于“堆栈”)缓冲区中独立初始化元素并非不可能,但这并不容易。

The problem is that defining an array causes the constructor to be called immediately.问题是定义数组会导致立即调用构造函数。 You'd have to define a char array (which has no constructor), and then construct and destroy the elements manually (using placement new and explicit destructor calls).您必须定义一个char数组(它没有构造函数),然后手动构造和销毁元素(使用放置 new 和显式析构函数调用)。 This isn't so hard unless you want exception safety, in which case the corner cases are very difficult to handle.除非您想要异常安全,否则这并不难,在这种情况下,极端情况很难处理。

If you're allowed to default-construct and then reassign the elements, it's easy, and covered by the other answers.如果您被允许默认构造然后重新分配元素,这很容易,并且被其他答案所涵盖。 If Complex has a working assignment operator, you should do this.如果Complex有一个工作赋值运算符,您应该这样做。

There is no such rule that constructor must have dynamic allocation for array.没有这样的规则,即构造函数必须对数组进行动态分配。

ac[i] = Complex( i, 2.0 );

is valid.已验证。 In fact you should avoid dynamic arrays, as much as you can.事实上,您应该尽可能避免使用动态 arrays。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM