Смещение и пропуск векторной ссылки - PullRequest
2 голосов
/ 01 мая 2011

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

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

private:
    int*   member;
    size_t numInts;
};

int* SomeClass::LockMember( size_t& 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 Ответ

1 голос
/ 01 мая 2011

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

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

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>& v)
{
    std::copy(v.begin(), v.end(), member.begin() + magicOffset);
}

Чтобы избежать копирования, возможно, что вы могли бы выделить память для двух векторов, одного для защищенной части и одногодля незащищенной части и используйте размещение 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, либо вернуть int&.

...