копирование std :: vector аннулировать * буфер, используя memcpy - PullRequest
1 голос
/ 03 марта 2020

У меня есть пользовательская функция, которая копирует значения в буфер

void foo(void *buffer, std::initializer_list<unsigned char> l) {
   memcpy(buffer, l.begin(), l.size());
}

Аргумент списка инициализатора принимает шестнадцатеричное значение в качестве параметра. Однако я хочу изменить его на строковое представление, например, вместо передачи параметра как {0x01, 0x02, 0x04}, я хотел бы передать его как «0x01 0x02 0x04».

Я изменил std::initializer_list<unsigned char> на std: :вектор. Но я получил неверную ошибку приведения от vector до void *.

void foo(void *buffer, std::vector<unsigned char> l) {
   memcpy(buffer, reinterpret_cast<void *>(l.begin()), l.size());
}

Ответы [ 3 ]

2 голосов
/ 03 марта 2020

std::vector::begin возвращает итератор , а не указатель на первый элемент. Попробуйте ...

void foo(void *buffer, std::vector<unsigned char> l)
{
    memcpy(buffer, l.data(), l.size());
}

Еще лучше: если вектор большой, вы можете рассмотреть возможность передачи по константной ссылке, а не по значению ...

void foo(void *buffer, const std::vector<unsigned char> &l)
{
    memcpy(buffer, l.data(), l.size());
}
1 голос
/ 03 марта 2020

Если использование memcpy не является абсолютным требованием, существует подход более высокого уровня:

std::uninitialized_copy(l.begin(), l.end(), (unsigned char*)buffer);

Но я бы сделал это более общим:

template <class Iter>
void foo(void *buffer, Iter first, Iter last) {
    typedef typename std::iterator_traits<Iter>::value_type *ptr;
    std::uninitialized_copy(first, last, static_cast<ptr>(buffer));
}

Это один работает с любым диапазоном и любым типом.

1 голос
/ 03 марта 2020

Хотя итераторы, возвращенные из .begin () или .end (), могут работать как указатели,
, но это не гарантирует, что они действительно являются псевдонимами реальных указателей.
Например, подумайте об итераторах из std::map .
Они должны содержать больше информации, а не только указатель, поскольку они выполняют итерацию по двоичному дереву.

Имеет смысл думать об итераторе из непрерывного контейнера как о указателе,
возможно, это действительно так, но помните, что стандарт C ++ не гарантирует этого.

В любом случае, вот мое решение.

void foo(void *buffer, std::vector<unsigned char> l) {
   memcpy(buffer, &*l.begin(), l.size());
}

выглядит странно, но выполняет свою работу правильно.
Решение другого ответа выглядит более элегантно, хотя:)

...