Смещение и передача векторной ссылки

#c #stl #vector #iterator

#c #stl #вектор #итератор

Вопрос:

При использовании массивов вы можете сделать что-то вроде

 class SomeClass
{
public:
    int* LockMember( size_tamp; numInts );

private:
    int*   member;
    size_t numInts;
};

int* SomeClass::LockMember( size_tamp; out_numInts )
{
    out_numInts = numInts - 1;
    return member   1;
}
  

Вернуть смещение массива на некоторую величину, чтобы предотвратить изменение кем-либо некоторой части условной памяти или, по крайней мере, показать некоторое намерение, чтобы эта часть условной памяти объекта оставалась нетронутой.

Поскольку я использую векторы везде, мне интересно, был ли какой-нибудь способ выполнить то же самое:

 class SomeClass
{
public:
    std::vector<int> LockMember( void );

private:
    std::vector<int> member;
};

std::vector<int> SomeClass::LockMember( void )
{
   // somehow make a vector with its beginning iterator pointing to member.begin()   1
   // have a size smaller by one, still the same end iterator. The vector must be 
   // pointing to the same data as in this class as it needs to be modifiable.

   return magicOffsetVector;
}
  

С заменой прокомментированной части реальным кодом. Есть идеи?

Комментарии:

1. Важно ли, чтобы две части находились в непрерывной памяти?

2. Это самое важное. Чем больше я думаю об этом, тем больше то, что я хочу, кажется невозможным. Потому что я пытаюсь получить свой пирог и съесть его одновременно. Память не может одновременно быть динамической и иметь автоматическую непрерывную часть, которую не нужно копировать при изменении размеров объектов. Ну что ж, кто не рисковал, тот ничего не потерял.

Ответ №1:

Если я вас правильно понимаю: вам нужна некоторая память, состоящая из двух частей: в начале вы хотите что-то, к чему нельзя прикоснуться, и после этого вы хотите что-то, что открыто для использования клиентским кодом.

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

 class SomeClass
{
public:
    std::vector<int> getMember( void ) const;
    void setMember(std::vector<int> newContent);

private:
    std::vector<int> member;
    size_t magicOffset;
};

// Read restricted part
std::vector<int> SomeClass::getMember( void ) const
{
    return vector<int>(member.begin()   magicOffset, member.end());
}

// Assign to restricted part
void SomeClass::setMember(const std::vector<int>amp; v)
{
    std::copy(v.begin(), v.end(), member.begin()   magicOffset);
}
  

Чтобы избежать копирования, возможно, вы могли бы выделить память для двух векторов, одного для защищенной части и одного для незащищенной части, и использовать placement new для помещения обоих векторов в эту память, таким образом гарантируя, что они находятся в непрерывной памяти. А затем предоставить клиентскому коду более или менее свободный доступ к общедоступной части вектора. Тем не менее, в vector все еще есть проблема с бухгалтерскими переменными, и в основном это был бы ужасный взлом, который только и ждет, чтобы взорваться.

Однако, если вам нужен только доступ к неограниченной части для каждого элемента, вы могли бы просто выполнить проверку диапазона аргументов, т.Е.:

 int getElement(size_t idx)
{
    idx  = magicOffset;
    if (idx > member.size() || idx < 0) throw std::out_of_range("Illegal index");

    return member[idx];
}
  

А затем либо предоставить setElement , либо вернуть intamp; .