2015-11-07 3 views
2

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

class Map 
{ 
    std::vector<Continent> continents; 

public: 

    Map(); 
    ~Map(); 
    Continent* getContinent(std::string name); 
}; 

Continent* Map::getContinent(std::string name) 
{ 
    Continent * c = nullptr; 
    for (int i = 0; i < continents.size(); i++) 
    { 
     if (continents[i].getName() == name) 
     { 
      c = &continents[i]; 
      break; 
     } 
    } 

    return c; 
} 

Здесь можно увидеть, что есть continent объекты, которые живут внутри vector под названием continents. Будет ли это правильным способом получения ссылки на объект, или есть ли лучший подход к этому? Есть ли основная проблема с вектором, который может привести к неправильной работе?

+0

, когда вектор динамически растет, его содержимое де-распределяется и перераспределяется. При таком сценарии неплохо получить ссылку на конкретный объект внутри вектора. – Nandu

+0

Быстрое и грязное исправление: используйте 'std :: list' вместо' std :: vector'. 'Std :: list' не отменяет указателей или ссылок при изменении размера. Только если вы удалите элемент из списка, указатель/ссылка будут недействительными. – PaulMcKenzie

+0

@PaulMcKenzie быстрый и грязный смысл хакерский? Будет ли использовать 'std :: list' правильную альтернативу? Будет ли иметь значение, если эти объекты будут жить в куче вместо этого; 'новый'? – Dimitri

ответ

1

Это нормально возвращает указатель или ссылку на объект внутри std::vector при одном условии: содержание вектора не должно измениться после того, как вы берете указатель или ссылку.

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

+0

Другими словами, если вектор является динамическим, я никогда не могу ссылаться ни на один из его объектов из-за недействительности указателей. Есть ли обходной путь? Что делать, если объекты были созданы в куче, а именно: std :: vector континенты. Означает ли это тот же вопрос? – Dimitri

+0

@Dimitri Вектор указателей на объекты кучи лучше, потому что добавление или удаление других указателей из вектора не отменяет существующих указателей. Единственная проблема заключается в том, что в какой-то момент вам нужно будет удалить эти объекты кучи, поэтому вам нужно будет что-то сделать с потенциальными оборванными указателями. Однако этот вопрос останется с векторами или без них. – dasblinkenlight

+0

Отлично, проблема с оборванными указателями будет рассмотрена в деструкторе карты. Но если они не делают недействительными при изменении внутри вектора, то это прекрасно. Мой вектор динамически растет во время чтения файла, который происходит один раз и только один раз. После создания объектов на основе того, что было прочитано в файле, они сохраняются в векторе и никогда не изменяются снова.Хотя мой подход будет работать в таком случае, я не уверен, что будущие требования потребуют изменения вектора. Но если не произойдет никакого признания, это хорошо. – Dimitri

1

Я бы посоветовал вам сделать что-то подобное выше. std :: vector делает некоторый причудливый способ обработки памяти, который включает изменение размера и перемещение массива, когда он находится вне емкости, что приведет к зависанию ссылки. С другой стороны, если в карте содержится вектор const, то есть гарантируется, что он не будет изменен, то, что вы делаете, будет работать.

Благодаря Sudharshan

1

Дизайн имеет недостатки, как указывали другие.

Однако, если вы не возражаете использовать больше памяти, потеряете тот факт, что последовательность больше не будет находиться в непрерывной памяти и что итераторы больше не являются произвольным доступом, тогда замена замены будет заключаться в использовании std::list вместо std::vector.

std::list не изменяет указатели или ссылки на внутренние данные при изменении размера. Единственный раз, когда указатель/ссылка недействителен, - это удаление объекта, указывающего/ссылающегося на него.

Смежные вопросы