我需要使用自定义分配器初始化的静态矢量数组,以便将我的数据(每个16字节)存储在外部ram中。我使用Howard Hinnant short alloc这样做,到目前为止一切顺利。
我使用GCC和C ++ 14:
Sequencer.h
using FixedVector = std::vector<SequencerNoteEvent, short_alloc<SequencerNoteEvent, kBytesChunkMax, 4>>;
/* memory pool */
static char sequencerNoteEvent[2][600] __attribute__((section(".masection")));
/* Declaration des différentes zones pour chaque vecteur */
static arena<600> arena0 __attribute__((section(".masection")));
static arena<600> arena1 __attribute__((section(".masection")));
/* Declaration des Vectors utilisants les pools */
static FixedVector v0 __attribute__((section(".masection")));
static FixedVector v1 __attribute__((section(".masection")));
Sequencer.cpp
// ---------------
// STATIC VARIABLE
// ---------------
char Sequencer::sequencerNoteEvent[kMaxChunks][kBytesChunkMax];
arena<kBytesChunkMax> Sequencer::arena0{Sequencer::sequencerNoteEvent[0]};
FixedVector Sequencer::v0{Sequencer::arena0};
arena<kBytesChunkMax> Sequencer::arena1{Sequencer::sequencerNoteEvent[1]};
FixedVector Sequencer::v1{Sequencer::arena1};
我从2个内存池开始,但我需要98304 ...而且我完全停留在初始化这些数组。
我试过这个:
Sequencer.h
/* Declaration de la memory pool */
static char sequencerNoteEvent[2][600] __attribute__((section(".masection")));
static arena<600> arenaa[2] __attribute__((section(".masection")));
static FixedVector v[2] __attribute__((section(".masection")));
Sequencer.cpp
arena<600> Sequencer::arenaa[]{Sequencer::sequencerNoteEvent[0], Sequencer::sequencerNoteEvent[1]};
FixedVector Sequencer::v[]{Sequencer::arenaa[0], Sequencer::arenaa[1]};
error: use of deleted function 'arena<N, alignment>::arena(const arena<N, alignment>&) [with unsigned int N = 600; unsigned int alignment = 4]'
arena<kBytesChunkMax> Sequencer::arenaa[]{Sequencer::sequencerNoteEvent[0], Sequencer::sequencerNoteEvent[1]};
如果我允许复制构造函数(这很可能是一个坏主意)
error: conversion from 'arena<600>' to non-scalar type 'pyrapro::FixedVector' {aka 'std::vector<pyrapro::SequencerNoteEvent, short_alloc<pyrapro::SequencerNoteEvent, 600, 4> >'} requested
FixedVector Sequencer::v[]{Sequencer::arenaa[0], Sequencer::arenaa[1]};
有人有任何其他方法来初始化这个吗?
编辑
非常感谢您的回答!实际上我需要用自定义分配器实例化我的向量(在我的情况下,short_alloc重定向到竞技场)。所以我需要用竞技场建造它们。每个竞技场都存储并在外部ram内存中分配一个数组,而short_alloc是自定义分配器本身,它满足标准的要求。
short_alloc(arena_type& a) noexcept : a_(a) {}
除非我已经构建了一个向量的分配器,否则我看不到任何其他解决方案。
竞技场中的移动构造函数解决了我的问题的一部分,我仍然有:
error: conversion from 'arena<600>' to non-scalar type 'pyrapro::FixedVector' {aka 'std::vector<pyrapro::SequencerNoteEvent, short_alloc<pyrapro::SequencerNoteEvent, 600, 4> >'} requested
当我这样做:
FixedVector Sequencer::v0{Sequencer::arena0};
我在初始化时调用short_alloc(arena_type&a),这很好。为什么我多次不能这样做?
当然如果有人有想法避免这个巨大的initializer_list我正在听!
我试着在short_alloc类中设置竞技场引用,但到目前为止还没有成功。引用不能为null,我不想更改所有这些代码,我没有用指针编写,初始化FixedVectors与虚拟竞技场的引用导致相同的初始问题。
谢谢,
问题是std::vector
的构造函数来自分配器is explicit。当你做FixedVector fv{myArena};
一切都很好,因为你在这里明确地构建了一个FixedVector
。但随着FixedVector
s阵列,你正在做list initialization。添加花括号是不够的,您需要明确拼写构造函数。
示例:
using FV = std::vector<int>;
using FVA = FV::allocator_type;
FVA fva[3]{};
//FV fv[]{1, 2, 3}; // error: cannot convert from int to vector<int>
//FV fv[]{{1}, {2}, {3}}; // ok (nested list initialization)
//FV fv[]{fva[0], fva[1], fva[2]}; // error: cannot convert from FVA to FV
FV fv[]{FV{fva[0]}, FV{fva[1]}, FV{fva[2]}}; // ok
请注意,这不仅乏味,而且还容易出现初始化顺序惨败。更不用说普通数组不是很好的现代C ++风格(但这是一个正交问题)。
arena
定义移动构造函数。你应该有这样的东西:
// template or something
class arena {
public:
arena(char arr[]) { /*...*/ }
// I assume you have it like this. It remains.
arena(const arena&) = delete;
// Define your move constructor if you don't have one and
// just move (assign) buffer pointers, etc. from moved instance to this.
// Same for move assignment operator.
arena(arena&&) = default;
arena& operator=(arena&&) = default;
// ...
};
然后行
arena<600> Sequencer::arenaa[]{Sequencer::sequencerNoteEvent[0], Sequencer::sequencerNoteEvent[1]};
将工作。编译器将隐式地将列表中的每个元素强制转换为arena<600>
,然后将内容移动到arenaa
数组元素。FixedVector
构造,因为显式的std::vector
构造函数具有单个分配器参数。
FixedVector Sequencer::v[]{Sequencer::arenaa[0], Sequencer::arenaa[1]};
固定:
FixedVector Sequencer::v[]{FixedVector{Sequencer::arenaa[0]}, FixedVector{Sequencer::arenaa[1]}};
在我的问题中,如果你想在这些数组中拥有超过9000个元素而不是2个,那么在初始化中我仍然无法填充你的静态数组。我想你不想在那些初始化列表中硬编码超过9000个元素。使用默认值(例如为空)初始化它们会更加聪明,然后在循环中分配所需的值。您可以围绕静态创建包装器结构,然后创建其静态实例,然后在结构构造函数中填充数组。这样的事情可能是:
class Sequencer {
static struct Wrapper {
using FixedVector = std::vector<SequencerNoteEvent>;
char sequencerNoteEvent[2][600];
arena<600> arenaa[2];
FixedVector v[2];
Wrapper() {
for (int i = 0; i < 2; i++) {
arenaa[i] = arena<600>(sequencerNoteEvent[i]);
v[i].emplace_back(arenaa[i]);
}
}
} s_instance;
};