首页 > 解决方案 > 如果 `std::array` 没有采用 `std::initializer_list` 的构造函数,那么初始化如何工作?

问题描述

有很多关于std::array用 a 初始化数据成员的问题和答案std::initializer_list,以及它是如何不可能的,因为没有std::array可用的构造函数。我想知道std::arraythen 的初始化是如何工作的?

当进行这样的调用时,引擎盖下会发生什么:

std::array<int, 4> a = {1,2,3,4};  // (1)

如果论证不是std::initializer_list<int>?

我试图通过查看libstdc++ 源代码来弄清楚初始化是如何工作的,并弄清楚_M_elems( __array_traits::_Tp) 做了什么,但我似乎找不到存储数据的数组的实际分配。然而,我看到它被到处使用:

       // Element access.
       _GLIBCXX17_CONSTEXPR reference
       operator[](size_type __n) noexcept
  { return _AT_Type::_S_ref(_M_elems, __n); }

并且_S_ref是一个constexpr似乎返回的函数nullptr

实际的数组数据在哪里声明?我可以理解编译器是否在幕后做某事,因为所有构造函数都是自动生成的,但我想知道会发生什么以及初始化调用 (1) 是如何可能的。

此外,如果我使用 anstd::array作为 N 维的数据成员Point,我找到了一个答案,建议如下:

template<std::size_t N, typename BT=double>
class Point 
{
    public: 

        Point() = default;

        template<typename ... Args>
        Point(Args&& ... args)
        :
            values_{std::forward<Args>(args)...} 
        {}

    private:

        std::array<BT, N>  values_; 
};

这使得可以做

Point<1> P1 {1.};   // (2)
Point<3> P3 {1.,2.,3.}; // (3)

我知道转发是必需的,因为(我理解为)(2,3)中使用的初始化列表是左值。但是,为什么需要大括号?如果我使用圆括号初始化values_

            values_(std::forward<Args>(args)...)    

我明白了

main.cpp: In instantiation of ‘Point<N, BT>::Point(Args&& ...) [with Args = {double}; long unsigned int N = 1; BT = double]’:
main.cpp:37:20:   required from here
main.cpp:14:48: error: no matching function for call to ‘std::array<double, 1>::array(double)’
             values_(std::forward<Args>(args)...)

标签: c++arraysc++11

解决方案


推荐阅读