Обход правил строгого псевдонима в C ++

Я хочу хранить ограниченное количество элементов в контейнере. Я не хочу использовать массив, потому что я хочу избежать ненужных вызовов конструктора объекта. Я не хочу использовать std::vector из-за неявного malloc вызов (я хочу минимизировать доступ к куче для максимальной согласованности кэша).

Поэтому я решил определить свой собственный контейнер, что-то вроде этого:

template<typename T, size_t capacity> class my_array {
private:
char buffer[sizeof(T)*capacity];
...
public:
T& operator[](size_t i) { return *(T*)&buffer[i*sizeof(A)]; }
...
};

Но когда я пытаюсь использовать этот контейнер, я получаю предупреждения компилятора о нарушении правил строгого алиасинга. Я прочитал о строгом псевдониме и понимаю, почему оптимизация компилятора может привести к сбою кода выше.

Как мне обойти это?

Что странно, что у моего компилятора нет претензий к моему кастому object_pool класс, который, среди прочего, я использую для пользовательского распределителя для своих ассоциативных структур данных STL. Этот класс выглядит очень похоже на вышеупомянутый (использует char[] и делает подобный актерский состав). Я не могу понять, в чем разница между ними.

1

Решение

использование std::array
, , , , , , , , , , , , , !

1

Другие решения

Если вы не собираетесь использовать std:array затем

char buffer[sizeof(T)*capacity];

должно быть

T buffer[capacity]

Вот почему поддержка шаблонов typenameв первую очередь.

1

использование std::aligned_storage если вы не хотите инициализировать объекты как std::array требует. Вы, вероятно, столкнетесь с проблемой выравнивания, так как ваша структура может быть назначена нечетному адресу.

Псевдоним с char массив для использования в качестве хранилища должен быть в порядке, я не уверен, о чем ваш компилятор. Это действительно минимальный тест?

1

Я выяснил загадочное решение, сравнивая точно с object_pool класс, на который я ссылался в моем первоначальном посте.

Я заменил

T& operator[](size_t i) { return *(T*)&buffer[i*sizeof(A)]; }

с

T* operator[](size_t i) {
if (...) {
return (T*)&buffer[i*sizeof(A)];
}
return NULL;
}

где ... любой предикат, который я знаю, всегда будет оценивать true, но который компилятор не достаточно умен, чтобы понять, всегда будет оценивать true,

Мне было бы любопытно, если кто-нибудь может объяснить точно, что происходит здесь через голову компилятора. Я использую gcc 4.4.3.

0
По вопросам рекламы [email protected]