2015-07-24 2 views
0

** Этот вопрос сильно отредактирован, чтобы обеспечить (узнав решение) пример проблемы в формате MCVE. MCVE, используемый для решения проблемы, можно найти по адресу this ideone link. ** (Если ideone.com удаляет сообщения, кто-то даёт мне знать!)Возможное недоразумение относительно std :: vector <T> object [arraySize]

Комментарии к этому сообщению включают ссылку на rextester link, у которой есть изменения, предоставленные @dyp (хотя я не знаю, как это может измениться со временем) **

template <typename T, size_t fD, size_t mD> 
class Field 
{ 
public: 
    // Constructor - the problem turned out to be here 
    Field(const Mesh<mD>& mesh, const std::string &fileName): 
     fileName_(fileName), 
     mesh_(mesh) 
    { 
     for (size_t d=0; d<fD; d++) { 
      field_[d].reserve(mesh.numCellS()); 
     } 
    } 

    // Copy constructor - maybe I've written this horribly? 
    Field(const Field<T,fD,mD>& refToCopy, const std::string &name): 
     fileName_(name), 
     mesh_(refToCopy.mesh_) 
    { 
     for (size_t d=0; d<fD; d++) { 
      field_[d] = refToCopy.field_[d]; 
     } 
    } 

    // Const Accessors 
    const std::vector<T> &x() const { return field_[0]; } 
    // some checking that fD is large enough 
    const std::vector<T> &y() const { return field_[1]; } 
    // Repeated, non-const. 

    void setZero(); 
    void setFixed(const T &val); 

private: 
    std::vector<T> field_[fD]; 
} 

template<typename T, size_t fD, size_t mD> 
void Field<T,fD,mD>::setZero() 
{ 
    setFixed(T(0)); 
} 

// This might need to be explicit. 
// Currently, 'a' can be converted for Field<double, D> 
template<typename T, size_t fD, size_t mD> 
void Field<T,fD,mD>::setFixed(const T &val) 
{ 
    for (size_t d=0; d<fD; d++) { 
     std::fill(field_[d].begin(), field_[d].end(), val); 
    } 
} 

Когда я пытаюсь получить доступ к значениям скопированного поля (не один построено с нуля), я получаю ошибку сегментации. Размещение std::cout << "field_[" << d << "][" << i << "] = " << field_[d][i] внутри цикла над i внутри копирования конструктор также бросает эту проблему (без какого-либо выхода, так что предположительно на первом значении i ...

Пример вызова может быть:

Field<double, 2, 2> fieldA(constructor arguments); 
fieldA.setZero(); // <- This is what I misunderstood 
Field<double, 2, 2> fieldB(fieldA, "copyOfFieldA"); 
std::cout << "fieldB.x()[5] = " << fieldB.x()[5] << std::endl; 

Где я не ошибаюсь? Должен ли я вместо этого использовать std::array<std::vector<T>>? Является ли это недопустимым способом доступа к полю? Или мой экземпляр-копирайтер просто неактивен (подозрительный случай).

+1

[Работает для меня] (http://rextester.com/YFCTK56876). MCVE или этого не произошло. –

+1

Я понятия не имею, какое странное расширение gcc позволяет это скомпилировать: 'field_ (refToCopy.field_)' Это незаконно; вы не можете скопировать массив через прямую инициализацию. clang ++ жалуется на это. Поскольку ваша копия ctor не делает ничего особенного, почему бы вам просто не оставить ее? – dyp

+0

[Эта ссылка] (http://rextester.com/live/QQW10887) должна скомпилировать и показать ошибку – chrisb2244

ответ

1

Чтобы подвести итог комментариям, я понимаю, что существует были проблемы с инициализацией поля (в частности распределение + инициализация векторных элементов в каждом измерении).

Полный текст на рабочем столе here.

Задача 1

фиксированного размера массива, объявленные как Type x[N] не может быть скопировать инициализирован с помощью синтаксиса x(y). Хотя обратите внимание, что it works с std::array s.

Задача 2

reserve влияет только на емкость стандартного контейнера, а не его размер. В частности, использование std::fill в зарезервированном, но не измененном размере контейнере ничего не делает.

Здесь нет обходного пути, кроме повторения на каждом элементе массива фиксированного размера для изменения размера (или assign) вручную.


В любом случае, я бы рекомендовал использовать 11 C++ std::array-х; нет накладных расходов, ваш код будет чище, и вы сможете более легко извлечь выгоду из операций перемещения.

+0

@dyp Хорошо, тогда, я думаю, вы опубликуете резюме, как только вы, ребята, пройдете через это время? Я просто удалю свой ответ :) – Sheljohn

+0

На самом деле, у меня нет много времени прямо сейчас для ответа. Не стесняйтесь писать, решая вопрос, который имел OP (как описано в комментариях). – dyp

+0

@dyp Это то, что вы имели в виду? – Sheljohn

1

Ответа на этот вопрос @dyp. Проводка, поскольку комментарии показывают, что он занят.

Конструктор использует field_[d].reserve(mesh.numCells());

Это оставляет памяти для записей, но не создает каких-либо записей. (Это я знал).

Последующее призвание fieldA.setZero() вызовов std::fill, которые также не создает записи (я пропустил этот момент)

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

Следовательно, самым простым решением является изменение field_[d].reserve(mesh.numCells()); на field_[d].resize(mesh.numCells()); в конструкторе Field.

+0

См. Также мой ответ ниже, выберите тот, который вам нравится. :) – Sheljohn

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