2013-05-14 3 views
2

Новое на C++, меня попросили сделать функцию в моем классе Matrix, который возвращает ссылку на значение в месте (i,j).Возвращение ссылки элемента std :: list из его итератора

В рамках задания, класс проводит array из std::list для представления матрицы:

list <value_type> * m_val; 

что не имеет особого смысла, но хорошо, что это назначение. Мне сказали, чтобы начать работать с этим:

template <class E> 
inline E& Matrix<E>::operator() (unsigned i, unsigned j) { 

} 

Это то, что я пробовал:

template <class E> 
inline E& Matrix<E>::operator() (unsigned i, unsigned j) { 
    list<value_type> row = m_val[i]; // Get the row 
    typename list<E>::iterator it = row.begin(); // Iterator at beginning of row 
    for (int x = 0; x < j; ++x) { 
     ++it; // For each column, I increase the iterator until I reach the desired spot 
    } 


    return *it; // I'm confused here. I got my iterator in the right spot, but I am not sure how to return a reference to its value. 
} 

Но, насколько я могу судить, это возвращает значение, а не ссылка. То, что я хочу достичь, по существу

myMatrix(2,3) = 50; // Now the value at 2,3 is 50. 
+0

Почему вам нужно * определить * шаблоны? Вам нужно только * использовать * стандартные контейнеры шаблонов .... –

+0

Вы хотите вернуть ссылку на целое число? – 2013-05-14 00:47:55

+0

@BasileStarynkevitch: Я думаю, класс Matrix должен содержать любую ценность. Извините, я не думаю, что полностью понимаю, что вы имели в виду. – Voldemort

ответ

1

list <value_type> * m_val;

Это не выглядит хорошо. Если вы уже используете стандартные контейнеры, почему бы не использовать std::vector < list<value_type > или std::array < list<value_type> >?

Помимо этого:

template <class E> 
inline E& Matrix<E>::operator() (unsigned i, unsigned j) { 
    // less error-prone with bounds-checking, as Remy Lebeau stated in a comment 
    if(i >= size_of_m_val_array) 
    { 
     throw std::out_of_range("first index out of range"); 
    } 

    //list<value_type> row = m_val[i]; // this would copy the list 
    list<value_type>& row = m_val[i]; 

    typename list<value_type>::iterator it = row.begin(); 

    // less error-prone with bounds-checking, as Remy Lebeau stated in a comment 
    if(j >= row.size()) 
    { 
     throw std::out_of_range("second index out of range"); 
    } 

    std::advance(it, j); 

    return *it; // correct :) `*it` returns a `value_type&` 
} 

Bounds проверка не является обязательным, хотя - просто обязательно документировать его (и указать его!), Если вы не проверить.

Я бы предпочел использовать E или value_type последовательно.

C++ 11 один вкладыш:

template < class E > 
inline E& Matrix<E>::operator() (unsigned i, unsigned j) 
{ 
    return std::next(m_val[i].begin(), j); 
} 
+0

Ах! Понимаю. Поэтому я копировал его =/.... большое спасибо! – Voldemort

+0

В первом примере не забудьте проверить 'it' для' end() 'перед разыменованием его, в случае, если' j' был вне пределов.Лучше всего ограничить проверку 'i'. –

+0

@RemyLebeau Я добавлю это к моему ответу, хотя проверка границ не является обязательной (например, оператор Std Containers ']' vs 'at()'). – dyp

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