【问题标题】:C++ : initialize(new) an array of vector of different initial sizeC ++:初始化(新)不同初始大小的向量数组
【发布时间】:2018-04-30 12:36:33
【问题描述】:

为了帮助你明白这一点,我给出了我的代码:(main.cpp),只涉及一个文件。

#include <iostream>
#include <vector>
using namespace std;
class test{
public : 
    int member {0};
    void fun(){cout << "member is " << member << endl;}
    test(){}
    //test(int param) : member(param){} //this line is commented.
};

int main()
{
    vector<test> *vp = new vector<test>[2] {{10},{20}};
    //vector<test> array[2] {{10},{20}};//this won't work either.
    cout << "size of vp[0] is " << vp[0].size() << endl;
    cout << "size of vp[1] is " << vp[1].size() << endl;
    return 0;
}

我打算将vp[0] 初始化为大小 10,将vp[1] 初始化为大小20。然而,当我使用g++ -std=c++11 main.cpp -o mainmac 上编译它时,它抱怨道:

main.cpp:14:45: error: chosen constructor is explicit in copy-initialization
    vector<test> *vp = new vector<test>[2] {{10},{20}};
                                            ^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:517:14: note: 
      constructor declared here
    explicit vector(size_type __n);
             ^
main.cpp:14:50: error: chosen constructor is explicit in copy-initialization
    vector<test> *vp = new vector<test>[2] {{10},{20}};
                                                 ^~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:517:14: note: 
      constructor declared here
    explicit vector(size_type __n);
         ^

在 CentOS Linux 中使用相同的命令,我得到了

main.cpp: In function ‘int main()’:
main.cpp:14:54: error: converting to ‘std::vector<test>’ from initializer list would use explicit constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = test; _Alloc = std::allocator<test>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<test>]’
     vector<test> *vp = new vector<test>[2] {{10},{20}};
                                                      ^
main.cpp:14:54: error: converting to ‘std::vector<test>’ from initializer list would use explicit constructor ‘std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const allocator_type&) [with _Tp = test; _Alloc = std::allocator<test>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<test>]’

这里发生了什么?为什么它与关键字explicit 有任何关系? 我知道向量有几个构造函数(例如具有初始化列表类型参数的构造函数)。如果我像vector&lt;test&gt; temp {10} 一样初始化向量,这会将向量初始化为大小为 10,而没有任何 explicit 问题。我不知道vector&lt;test&gt; array[2] {{10},{20}} 里面隐藏了什么导致了我的错误。

有趣的是,如果我为类test 提供一个带有一个参数的构造函数(只需取消注释我的代码中的行),编译器根本不会抱怨。但是vector&lt;test&gt; array[2] {{10},{20}}的含义改成了用test分别用1020初始化的2个test类型对象来初始化向量array[0]。但是我后来尝试的语法vector&lt;test&gt; array[2] {10,20}又错了。

我不知道这里发生了什么,我完全迷路了。 {10,20} 不也是初始化列表类型吗?

如果你能解释一下这里发生了什么,以及如何初始化一个不同大小的向量数组,我真的很感激(请不要使用规避方式)。我想知道语法到底是什么意思。

【问题讨论】:

  • 对于初学者,不要使用指向向量的指针,也不要使用new。使用对象向量并让它完成所有分配。
  • 这是一个骗局。要点是列表初始化不允许直接初始化
  • @Ron 谢谢!如果你能解释一下这里发生了什么,我真的很感激。
  • vector&lt;test&gt; *vp = new vector&lt;test&gt;[2] {{10},{20}}; -> std::vector&lt;std::vector&lt;test&gt;&gt; data = {std::vector&lt;test&gt;(10), std::vector&lt;test&gt;(20)};
  • @PasserBy 谢谢!我在询问之前进行了搜索。

标签: c++ arrays vector initialization initializer-list


【解决方案1】:

首先,explicit 构造函数可以直接初始化,但不能复制初始化。

那么,在aggregate initialization

(强调我的)

每个direct public base, (since C++17) 数组元素或非静态类成员,按照类定义中数组下标/外观的顺序,从初始化列表的相应子句中复制初始化

这意味着new vector&lt;test&gt;[2] {{10},{20}};{10}{20} 用于复制初始化 vector&lt;test&gt; 元素;那么explicit 构造函数不被考虑。

如果我像 vector&lt;test&gt; temp {10} 这样初始化向量,这会将向量初始化为大小为 10,而没有任何 explicit 问题。

因为explicit允许在direct initialization中使用构造函数,

直接初始化比复制初始化更宽松:复制初始化只考虑非显式构造函数和非显式用户定义转换函数,而直接初始化考虑所有构造函数和所有用户定义转换函数。

出于同样的原因,new vector&lt;test&gt;[2] {std::vector&lt;test&gt;{10},std::vector&lt;test&gt;{20}}; 也可以使用。

顺便说一句:

如果我为类test 提供一个带有一个参数的构造函数(只需取消注释我代码中的行),编译器根本不会抱怨。

如果你提供了一个可以用来将int隐式转换为test的构造函数,那么{10}可以用来构造一个std::initializer_list&lt;test&gt;,那么std::vector&lt;test&gt;的构造函数就是std::initializer_list&lt;test&gt;调用,因为它总是首选。顺便说一句,如果您创建 test explicit 的构造函数,代码也会失败。

【讨论】:

    【解决方案2】:

    您正在使用代码初始化vector&lt;test&gt; 对象:vector&lt;test&gt; array[2] {{10},{20}}。您得到的错误来自使用vector::vector(size_t count) constructorexplicit。这个vector 构造函数将构造count 默认构造的test 对象。
    因此,例如,如果它没有被定义为explicit,那么您最终会得到包含 10 个默认构造的 test 对象的 array[0] 和包含 20 个默认构造的 test 对象的 array[1]。如果您打算这样做,则必须明确构造 vector 对象:

    vector<test> foo[] = { vector<test>{ 10 }, vector<test>{ 20 } }
    

    您确实想将测试对象构造到vectors 中,所以这个eplicit 实际上是在保护您免于意外分配意外的vectors。

    当你在test:test(int param)构造函数中添加{{10},{20}}仍然无法使用explicitvector构造函数。但现在可以将其视为list initializationvector[0]。但类似于如果你已经完成:int array[2] = {42} 和 2nd 元素将被零初始化;在这种情况下,您的 2ndvector 也将未初始化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-08
      • 2017-08-03
      • 1970-01-01
      • 2018-12-31
      • 2022-12-31
      • 1970-01-01
      相关资源
      最近更新 更多