Можно ли использовать std :: vector <char>для выделения памяти с выбранным выравниванием памяти? - PullRequest
4 голосов
/ 17 марта 2019

Я копирую память процесса в буфер vector<char> и хотел бы, чтобы память, выделенная для этого вектора, имела более высокое выравнивание, чем просто значение по умолчанию.

Это потому, что я ищу произвольно типизированные шаблоны в том буфере, где память может представлять что угодно - я ожидаю, что любая пара значение / тип, которую я ищу, будет выровнена в соответствии с ее типом.

Возможно, я мог бы решить эту проблему с помощью 'смещения', но я бы предпочел, чтобы мой буфер символов был выровнен.

Есть ли способ сделать это, кроме создания vector<large_type> вместо этого?

Ответы [ 2 ]

3 голосов
/ 17 марта 2019

Я мог бы решить мою проблему с помощью пользовательского распределителя .

Пример с boost::alignment::aligned_allocator

#include <vector>
#include <boost/align/aligned_allocator.hpp>

template <typename T>
using aligned_vector = std::vector<T, boost::alignment::aligned_allocator<T, 16>>;
// 16 bytes aligned allocation

См. Также Как выровнять данные вектора.

0 голосов
/ 17 марта 2019

Я использовал для этой цели что-то вроде следующего:


#include <iostream>
#include <vector>

template<typename T>
class AlignedVector {
 public:
  AlignedVector() : data_(nullptr) {}
  AlignedVector(int n)
      : char_vec_(sizeof(T)*(n+1)),
        data_(AlignedAddr(char_vec_.data())),
        size_(n) {}

  T* operator[](size_t n) { return data_[n]; }
  const T* operator[](size_t n) const { return data_[n]; }

  T* data() { return data_; }
  const T* data() const { return data_; }

  size_t size() const { return size_; }
  void resize(size_t n) {
    char_vec_.resize(sizeof(T)*(n+1));
    data_ = AlignedAddr(char_vec_.data());
    size_ = n;
  }

 private:
  static T* AlignedAddr(char* addr) {
    return (T*)(addr + sizeof(T) - ((size_t)addr % sizeof(T)));
  }

  std::vector<char> char_vec_;
  T* data_;
  size_t size_;
};

int main()
{
  AlignedVector<int[128]> vec(13);
  std::cout << (size_t)vec.data() << std::endl;
}

Основной функцией, выполняющей выравнивание, является static T* AlignedAddr(char* addr). В основном для массива типа N * element T мы выделяем достаточный размер для (N + 1) элементов и возвращаем наименьший выровненный адрес внутри выделенной области.

Чтобы включить другие методы в std::vector<T>, необходимо реализовать их, используя data_ и size_ по отдельности. Это сработало для меня, так как я обычно использую только несколько из них.

...