将包含C样式数组的对象初始化为成员变量(C++)

Initialize object containing C-style array as member variable (C++)

本文关键字:成员 变量 C++ 初始化 对象 包含 样式 数组      更新时间:2023-10-16

考虑以下代码:

struct Color  // This struct can't be modified
{
double grey;
double rgb[3];
};
int main()
{
double myRGB[3] = {2, 6, 9};
Color c = {10, myRGB}; // This line doesn't work
return 0;
}

如何在一行中初始化Color对象?

在我的真实场景中,不能更改Color结构(例如,使用std::array而不是C样式数组(。

由于Color是一个聚合,您可以使用聚合初始化,并将数组初始化器直接放在大括号中,如

Color c = {10, {2, 6, 9}};

如果必须用数组初始化c,由于它很小,您可以像一样展开它

Color c = {10, {myRGB[0], myRGB[1], myRGB[2]}};

假设需要使用中间数组,下面是如何做到的:

#include <utility>
#include <cstddef>
struct Color  //this struct can't be modified
{
double grey;
double rgb[3];
};
template<size_t N, size_t... IX>
auto make_c_impl(double grey, double (&rgb)[N], std::index_sequence<IX...>) {
static_assert(sizeof(rgb) == sizeof(Color::rgb), "Arrays sizes must match!");
return Color{grey, {rgb[IX]...}};
}
template<size_t N>
auto make_c(double grey, double (&rgb)[N]) {
return make_c_impl(grey, rgb, std::make_index_sequence<N>{});
}
double myRGB[3] = {2, 6, 9};
Color c = make_c(10, myRGB); //this line now works

请注意,在任何级别的优化下,此代码实际上都不会产生任何不必要的复制。

作为对其他答案的补充,错误是因为在c++中,数组是不可复制的,并且尝试从lvalue初始化数组具有调用copy-constructor的语义,与相同

double r1[3] = {0., 0., 0.};
double r2[3] {r1} // doesn't compile

您的选择是:

  • 像@NathanOliver那样做list-initialization
  • 或者如@SergeyA答案中那样扩展数组的元素以形成CCD_ 9

说我是骗子,但是。。。

struct Color final  
{
double grey;
double rgb[3];
};
// the cheet
#define make_color( x, a, b ) Color x { a, b[0], b[1], b[2] }
int main()
{
double myRGB[3]{ 2, 6, 9 };
make_color( c, 10, myRGB ) ; // single line construction 
printf("nColor grey: %ft rgb:[ %f, %f, %f ]", c.grey, c.rgb[0], c.rgb[1], c.rgb[2] ) ;
}

但是,由于这是一个非常糟糕的C++,我自由地制作了一些稍微好一点的东西。。。

struct Color final  
{
double grey;
double rgb[3];
};
auto  make_color ( double a, const double(&b)[3] ) { return Color { a, b[0], b[1], b[2] }; }; 
auto  make_color ( double a, double b, double c, double d ) { return Color { a, b, c, d }; }; 
auto print_color ( Color c ) { printf("nColor grey: %ft rgb:[ %f, %f, %f ]", c.grey, c.rgb[0], c.rgb[1], c.rgb[2] ) ; }
//
int main()
{
double myRGB[3]{ 2, 6, 9 };
auto c = make_color( 10, myRGB ) ; 
print_color(c);    
auto z = make_color( 10, 0xFF, 0xA0, 0xB0 ) ; 
print_color(z);    
}

所有这些都是一个好的老SO传统:不要质疑这个问题:(

(此处为必填Wandbox(

ps:我喜欢你的方法Oliver,当然你在那些init列表中不需要双大括号。