【发布时间】:2017-11-24 13:11:19
【问题描述】:
我有一个静态大小数组的别名,使用起来很简单:
using triplet_t = std::uint8_t[3];
// vvvvvvvvvvvvvvvvvv <--- easier than std::uint8_t(&triplet)[3]
void f(const triplet_t &triplet) { /* whatever */ }
triplet_t t{}; // As good as std::uint8_t t[3]{};
t[0] = '0';
t[1] = '1';
t[2] = '2';
for (auto &v : t) std::cout << v << ' ';
std::cout << '\n';
// So far so good...
triplet_t t3[3]{};
for (auto &r : t3)
for(auto &v : r)
v = 42;
我什至可以在容器中使用别名:
std::vector<triplet_t> vt;
或者我以前是这么想的,因为一旦你使用vt,它就会失败:
vt.push_back({});
GCC 8.0.0 201711
error: parenthesized initializer in array new [-fpermissive] { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ error: request for member '~unsigned char [3]' in '* __p', which is of non-class type 'unsigned char [3]' destroy(_Up* __p) { __p->~_Up(); } ~~~~~~^~~
问题似乎在于,在展开所有模板技巧后,将调用placement-new 来转发所有带括号提供的参数,显然这不是初始化静态大小数组的方法。
此外,不知何故,容器将triplet_t 视为一个对象,因此要求使用析构函数,再次编译失败。没有别名,问题显然是一样的:
std::vector<std::uint8_t[3]> vt;
vt.push_back({}); // Boom!
vt.push_back({255, 0, 0}); // Ouch!
但使用具有相同内存布局的struct 没有问题:
struct rgb { std::uint8_t r, g, b; };
std::vector<rgb> vt;
vt.push_back({}); // Nice!
vt.push_back({255, 0, 0}); // Cool!
我想知道为什么会发生这种情况,有没有办法在容器中使用静态大小的数组作为包含类型?
【问题讨论】:
-
“有没有办法在容器中使用静态大小的数组作为包含类型?”应该可以使用
std::array。 -
C 数组不可复制。
-
你和
using triplet_t = std::array<std::uint8_t,3>得到同样的结果吗? -
结构包装器可能会有所帮助。
struct chocolate { std::uint8_t[3] nougat; }. -
@Jarod42 你的评论让我想到了为什么人们会问关于 C/C++ 的问题
标签: c++ stl containers