如何初始化包含引用成员的结构体数组?

问题描述 投票:0回答:3

例如:

struct thing1 {
    int very_important_integer = 5;
};

struct thing2 {
    thing1 &thing;
    thing2(thing1 &A) : thing(A) {}
};

int main() {
    // in practice, this array is 49,500 elements large, not just 5
    thing1 stuff[5]; // OK
    thing2 arr[5];   // error: no default constructor for thing2
}

我无法向

thing2
添加默认构造函数,因为有一个要初始化的引用。

c++ arrays initialization c++17
3个回答
4
投票

不确定这是否是您想要的,但这是唯一的选择 - 在创建时初始化元素。

struct thing1 {
  int veryimportantinteger = 5;
};

struct thing2 {
  thing1& thing;
  thing2(thing1& A) : thing(A) {}
};

int main() {
  thing1 stuff[5];
  thing2 arr[5]{stuff[0], stuff[1], stuff[2], stuff[3], stuff[4]};
}

带有指针的示例

struct thing2 {
  thing1* thing{};
  thing2() = default;
  thing2(thing1& A) : thing(&A) {}
};

int main() {
  thing1 stuff[5];
  thing2 arr[5]{};
  for (size_t i = 0; i < std::min(std::size(arr), std::size(stuff)); ++i)
    arr[i] = stuff[i];
}

0
投票

您可以使用

placement-new
来构造
arr[]
的数组元素,从而允许您在每个元素上调用
thing2
构造函数,即在循环中:

struct thing1{
  int veryimportantinteger = 5;
};

struct thing2{
  thing1 &thing;
  thing2(thing1 &A):thing(A){}
};

int main(){
  thing1 stuff[5];
  char buffer[sizeof(thing1)*5];
  thing2 *arr = reinterpret_cast<thing2*>(buffer);
  for (int i = 0; i < 5; ++i){
    new (&arr[i]) thing2(stuff[i]);
  }
  //use arr as needed...
  for (int i = 0; i < 5; ++i){
    arr[i].~thing2();
  }
}

在现代 C++ 中,您应该使用

std::aligned_storage
/
alignas
std::launder
std::construct_at()
/
std::destroy()
等来使代码更安全/正确,但基本原则仍然存在 - 预先分配一个足够大小的缓冲区,在缓冲区中适当的偏移处放置构造每个对象,根据需要使用对象,然后在使用完缓冲区后销毁它们。


0
投票

如果您将 c-array 更改为

std::array
,您可以创建一个函数来创建数组:

// const variant omitted.
// C++20
template <typename T, std::size_t N, typename From>
std::array<T, N> make_array_from(std::array<From, N>& froms) {
    return [&]<std::size_t... Is>(std::index_sequence<Is...>) {
        return std::array<T, N>{{T{froms[Is]}...}};
    }(std::make_index_sequence<N>());
}

// C++17
template <typename T, std::size_t N, typename From, std::size_t... Is>
std::array<T, N> make_array_from_impl(std::index_sequence<Is...>, std::array<From, N>& froms) {
    return std::array<T, N>{{T{froms[Is]}...}};
}

template <typename T, std::size_t N, typename From>
std::array<T, N> make_array_from(std::array<From, N>& froms) {
    return make_array_from_impl(std::make_index_sequence<N>(), froms);
}

随着使用

std::array<thing1, 5> stuff{/*..*/};
auto arr = make_array_from<thing2>(stuff);

演示

© www.soinside.com 2019 - 2024. All rights reserved.