Существует два способа избежать копирования, о которых я знаю и которые видел в использовании.
Традиционным способом действительно является передача указателя / ссылки на известную сущность. Хотя это работает нормально и с минимальной суетой, проблема в том, что он связывает вас с данным представлением, что в случае необходимости влечет за собой преобразования (как вы уже видели).
Другой способ, который я обнаружил с помощью LLVM:
Идея поразительно проста: оба держат T*
, указывающий на начало массива T
, и size_t
, указывающий количество элементов.
Что волшебно, так это то, что они полностью скрывают фактическое хранилище, будь то string
, vector
, динамически или статически размещенный C-массив ... это не имеет значения. Представленный интерфейс является полностью унифицированным и не требует копирования.
Единственное предостережение в том, что они не овладевают памятью (Ref
!), Поэтому могут появиться тонкие ошибки, если вы не позаботитесь о них. Тем не менее, это нормально, если вы используете их только во временных операциях (например, внутри функции) и не сохраняете их для дальнейшего использования.
Мне показалось, что они невероятно удобны при работе с буфером, особенно благодаря бесплатным операциям нарезки. С диапазонами гораздо проще работать, чем с парами итераторов.
Есть и третий способ, который я испытал, но до сих пор никогда не использовал в серьезном коде. Идея состоит в том, что vector<unsigned char>
является представлением очень низкого уровня. Подняв уровень абстракции и используя, скажем, класс Buffer
, вы можете полностью инкапсулировать точный способ хранения памяти, чтобы она не стала проблемой для вашего кода.
И затем, не стесняйтесь, выбирайте одно представление памяти, которое требует меньшего преобразования.