简体   繁体   English

为什么用户定义类型的数组必须调用其默认构造函数?

[英]Why does an array of user defined type have to call the default constructor thereof?

Please consider the following example 请考虑以下示例

struct Foo
{
    int bar;    
    Foo(int i):bar(i){cout << "real ctor\n";}   
    Foo(){cout << "default ctor\n";}
};

int main()
{   
    Foo fooArr[3];//default ctor called 3 times 
    for(int i=0;i!=3;++i)cout << fooArr[i].bar << endl;//bare memory junk
    cout << endl;

    vector<Foo> fooVec;
    for(int i=0;i!=3;++i){
        fooVec.push_back(Foo(i));     //only real ctor called
        cout << fooVec[i].bar << endl;//real thing 
    }
    cout << endl;

    int iArr[3];
    for(int i=0;i!=3;++i)cout << iArr[i] << endl;//bare memory junk
}

I don't want any user of Foo to call its default constructor, because it's not in my design. 我不希望Foo任何用户调用其默认构造函数,因为它不在我的设计中。 But I'd like my users to be able to use an array of Foo , to support that, I was forced to provide a pointless and confusing Foo::Foo(). 但是我希望用户能够使用Foo数组来支持这一点,因此我不得不提供一个毫无意义且令人困惑的Foo :: Foo()。 I just don't understand why does the C++ standard force programmers to do such a thing. 我只是不明白为什么C ++标准会迫使程序员去做这样的事情。 What is the rationale behind it? 其背后的原理是什么? Why the inconsistency? 为什么不一致? Could any of you smart guys who get this explain it to me, please? 你们中任何一个懂这个的聪明人都可以向我解释一下吗? Thanks in advance! 提前致谢!

You can make arrays of Foo even if it doesn't have a default constructor. 您可以创建Foo数组,即使它没有默认构造函数也是如此。 It's just that the elements have to be constructed when you declare the array. 这只是元素具有在声明数组构造。 So you can do this: 因此,您可以执行以下操作:

Foo fooArr[] = { Foo( 1 ), Foo( 2 ), Foo( 3 ) };

The alternative is to use aa dynamic array (your vector<Foo> example, which is probably best) or an array of pointers to Foo (like shared_ptr<Foo> arrFoo[3] ) 另一种选择是使用一个动态数组(您的vector<Foo>示例,可能是最好的)或一个指向Foo的指针数组(例如shared_ptr<Foo> arrFoo[3] )。

shared_ptr<Foo> arrFoo[3];
arrFoo[2].reset( new Foo(3) );

A final note about vector<Foo> : since the size of the array is known in advance, you can improve performance by reserving enough space in the vector for all future Foo s: 关于vector<Foo>最后一点说明:由于数组的大小是事先已知的,因此可以通过为所有将来的Foo保留向量中的足够空间来提高性能:

vector<Foo> arrFoo;
arrFoo.reserve( 3 );

for( int i = 0; i<3; ++i )
    arrFoo.push_back( Foo( i ) );

EDIT: Your question was why do you have to have a default constructor to make a static array of the type. 编辑:您的问题是为什么您必须具有默认构造函数才能创建类型的静态数组。 I thought the answer was clear but I'll try to explain it. 我以为答案很明确,但我会尽力解释。

Foo bar1; Foo bar2; creates two objects using the default constructor, since no arguments were provided. 因为没有提供参数,所以使用默认构造函数创建两个对象。

Foo bar[2]; is essentially the same thing. 本质上是同一件事。 It declares two objects that need to be constructed. 它声明了两个需要构造的对象。 There is no way to declare an object without constructing it - that's the very point of declaring it in the first place. 没有构造它就无法声明一个对象-这就是首先声明它的目的。

A static array in C++ is just a bunch of objects placed contiguously memory. C ++中的静态数组只是一堆连续放置在内存中的对象。 It's not a separate object. 它不是一个单独的对象。

Hope that makes sense. 希望有道理。

The rationale is that the array is full of default constructed elements, so the type of the elements must be default constructible. 理由是数组中充满了默认构造的元素,因此元素的类型必须是默认可构造的。 If you initialized the array with some values, the default construction wouldn't be required: 如果使用一些值初始化数组,则不需要默认构造:

Foo fooArr1[3]; // full of default constructed Foos
Foo fooArr[3] = {1,2,3}; // default constructor not required. Foo(int) called.

Note that the second line in the code example uses the implicit conversion from int to Foo provided by the implicit Foo(int) converting constructor. 请注意,代码示例的第二行使用隐式Foo(int)转换构造函数提供的从intFoo的隐式转换。

The reason you have to provide your own default constructor is that you have declared one constructor, which disables the automatic generation of the default constructor. 您必须提供自己的默认构造函数的原因是,您已经声明了一个构造函数,这将禁用默认构造函数的自动生成。 The rationale behind this is that if you need to provide some constructor, it is likely that you also want to do something special in the default constructor. 其基本原理是,如果您需要提供一些构造函数,则可能还需要在默认构造函数中做一些特殊的事情。

If you really are worried about user provided constructors, then you can make your class a real aggregate and use aggregate initialization: 如果您真的担心用户提供的构造函数,那么可以使您的类成为真正的聚合并使用聚合初始化:

struct Foo
{
  // no user declared constructors
  int foo;
};

int main()
{   
    Foo fooArr1[3]; // OK
    Foo fooArr[3] = { {1}, {2}, {3} }; // aggregate construction 
}

In C++11 you can enable the compiler generated default constructor using default : 在C ++ 11中,您可以使用default启用编译器生成的默认构造函数:

Foo()=default;

You have to choose: either not defining a default constructor, and therefore, you can't declare an array of Foo . 您必须选择:不定义默认构造函数,因此,您不能声明Foo数组。 Or declaring a default constructor (empty even) and can declare an array of Foo . 或者声明一个默认的构造函数(空偶),并且可以声明一个Foo数组。

If you have dealt before with OOP languages such as C# or Java, and you have a class Foo and Foo[] arr , then you don't have to declare default constructor, because the array in these languages carries only references (addresses) to objects. 如果您之前使用过C#或Java之class Foo OOP语言,并且拥有class FooFoo[] arr ,则不必声明默认构造函数,因为这些语言中的数组仅携带对以下内容的引用(地址):对象。 The array itself is an object, so arr when created will == null . 数组本身是一个对象,因此创建时arr将== null When using arr = new Foo[3]; 当使用arr = new Foo[3]; then we make a new object of array that contains 3 references: arr == { null, null, null } . 然后我们创建一个包含3个引用的数组新对象: arr == { null, null, null } Then you assign an object to each reference: for (int i = 0; i < 3; ++i) arr[i] = new Foo(i); 然后为每个引用分配一个对象: for (int i = 0; i < 3; ++i) arr[i] = new Foo(i); .

However, C++ is different because the arrays carry the object itself rather than a reference to it. 但是,C ++有所不同,因为数组携带对象本身而不是对象的引用。 So, when carrying the object itself, it must have no-parameter constructor to be called with each object. 因此,在携带对象本身时,它必须具有无参数构造函数才能与每个对象一起调用。 (ie in C++: Foo arr[3]; then arr = { objectOfFoo, objectOfFoo, objectOfFoo } (即在C ++中: Foo arr[3];然后arr = { objectOfFoo, objectOfFoo, objectOfFoo }

A solution to your problem may found by decalring an array of pointers: 通过对指针数组进行除垢可以找到解决问题的方法:

Foo * arr[10] = { 0 }; // arr = { NULL, NULL, NULL, ... , NULL }
for (int i = 0; i < 10; ++i) arr[i] = new Foo(3); // you don't have to declare default constructor

// some using of array
// C++ doesn't have a garbage collector
for (int i = 0; i < 10; ++i) delete arr[i];

暂无
暂无

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

相关问题 为什么这会调用默认构造函数? - Why does this call the default constructor? 为什么空向量调用值类型的默认构造函数? - Why does an empty vector call the value type's default constructor? 如果我们创建用户定义的复制构造函数,为什么编译器不提供默认构造函数? - Why does the compiler not provide default constructor, if we create a user defined copy constructor? 在std :: array中的元素上调用用户定义的构造函数 - Call user defined constructor on elements in std::array 为什么 static 和用户定义的 class 类型的局部变量的合成默认构造函数的行为不同? - Why different behaviour of synthesized default constructor for static and local variable of user defined class type? 为什么删除副本构造函数会影响用户定义的默认构造函数? - Why deleting copy constructor affects user-defined default constructor? 为什么QAction没有默认构造函数? - Why does QAction not have a default constructor? 为什么`std :: pair`允许使用用户定义的删除move构造函数从类类型的右值进行初始化? - Why does `std::pair` allow to initialize from an rvalue of class type with a user-defined deleted move constructor? 为什么复制构造函数调用其他类的默认构造函数? - Why does copy constructor call other class' default constructor? 为什么调用重载的构造函数会导致调用默认构造函数? - Why does calling an overloaded constructor cause a call of the default constructor?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM