【问题标题】:Why I can't desalinize std::array like this? [duplicate]为什么我不能像这样淡化 std::array ? [复制]
【发布时间】:2017-01-12 13:40:00
【问题描述】:

为什么我不能像这样淡化 std::array ?

#include <array>

struct Point
{
    float x;
    float y;
};

int main()
{
   std::array<Point, 3> m_points { 
      { 1.0f, 1.0f }, 
      { 2.0f, 2.0f }, 
      { 3.0f, 3.0f }
   };
}

这样做我得到错误:

错误:std::array&lt;Point, 3ul&gt; 的初始化程序太多

但它的工作原理是这样的:

std::array<Point, 3> m_points { 
   Point{ 1.0f, 1.0f }, 
   Point{ 2.0f, 2.0f }, 
   Point{ 3.0f, 3.0f } 
};

相比之下,std::map 可以用以下两种方式初始化:

   std::map<int, int> m1 {std::pair<int, int>{1,2}, std::pair<int, int>{3,4}}; 
   std::map<int, int> m2 {{1,2}, {3,4}};

【问题讨论】:

  • 大括号数量错误?试试std::array&lt;Point, 3&gt; m_points {{{ 1.0f, 1.0f }, { 2.0f, 2.0f }, { 3.0f, 3.0f }}};Seems to work...
  • 我认为问题在于编译器不知道您要在第一个示例中初始化什么结构。即使你告诉数组它看不到你想要的类型Point
  • 我以前从未在这种情况下听说过desalinize。我推断它的意思是初始化?
  • 这种情况下desalinize是什么意思?
  • @Narek,c'tor 类型。 std::arrays 都是隐式声明的。 std::map 有一个 c'tor 采用 std::initializer_list

标签: c++ initialization aggregate c++14 declaration


【解决方案1】:

在此声明和初始化

   std::array<Point, 3> m_points { 
      { 1.0f, 1.0f }, 
      { 2.0f, 2.0f }, 
      { 3.0f, 3.0f }
   };

编译器将大括号中的第一个初始化程序视为整个数组(内部聚合)的初始化程序。 std::array 是一个包含另一个聚合的聚合。

改写

   std::array<Point, 3> m_points {
      { 
      { 1.0f, 1.0f }, 
      { 2.0f, 2.0f }, 
      { 3.0f, 3.0f }
      }
   };

第二种情况

std::array<Point, 3> m_points { 
   Point{ 1.0f, 1.0f }, 
   Point{ 2.0f, 2.0f }, 
   Point{ 3.0f, 3.0f } 
};

每个初始值设定项被依次视为内部聚合的下一个元素的初始值设定项。

考虑这个简单的演示程序。

#include <iostream>

struct array
{
    int a[10];
};

int main()
{
    array a = { { 0, 0 }, { 1, 1 } };

    return 0;
}

编译器发出类似的错误

prog.cpp:14:33: error: too many initializers for 'array'
  array a = { { 0, 0 }, { 1, 1 } };
                                 ^

那就是它决定{ 0, 0 } 是内部数组(内部聚合)的初始化器。因此,大括号中的下一个初始化程序在外部聚合(结构)中没有相应的数据成员。

【讨论】:

  • 我完全不明白为什么再添加两个花括号就可以解决问题。
  • @Narek,因为使用额外的一对花括号(或 =),您将进行聚合初始化。
  • @StoryTeller 也许和类比的例子会澄清?
  • @Narek 通常 std::array 被定义为包含数组的结构。外部大括号内的第一个大括号被视为该数组的初始化器。当有多个大括号时,编译器会决定初始化器的数量多于聚合的成员。
  • @Narek,因为标准将其定义为裸阵列的灯座,因此可以进行聚合初始化。上面链接的 dup 对此非常有描述性。
【解决方案2】:

std::array 没有明确定义的构造函数,不像其他标准容器,如std::vectorstd::map,但只有自动提供的构造函数。使用std::vector,编译器将尝试将您的表达式与每个可用的构造函数和类似的构造进行匹配

std::vecor<Point> m_points { {1.0f,1.0f}, {2.0f,2.0f}, {3.0f,3.0f} };

找到与构造函数的匹配项

std::vector::vector(initializer_list<T>, const Allocator& = Allocator() );

但是对于std::array,它必须使用底层数组的聚合初始化(在您的情况下为Point[3]),因此您的构造不匹配。要让它工作,你必须添加另一对大括号

std::array<Point, 3> m_points { 
  { { 1.0f, 1.0f },
    { 2.0f, 2.0f }, 
    { 3.0f, 3.0f } }
};

【讨论】:

  • 为什么我必须处理 std::array 的内部实现?我只想初始化它,我不在乎它是如何设计的。你同意这很糟糕吗?
  • 这是另一个完全不同的问题。不要指望你(最初)没有问的问题的答案。
  • cmets 中都没有? :)
猜你喜欢
  • 2015-02-09
  • 2018-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
相关资源
最近更新 更多