Почему ошибочно возвращать адрес элемента std :: vector через функцию const? - PullRequest
0 голосов
/ 29 сентября 2018

Я посмотрел на следующие потоки, но они не говорят о const ness функций, возвращающих адрес:

(1) Возвращение указателя на элемент вектора в c ++

(2) Можно безопасно возвращать адрес значения std :: map?

В коде:

class test_c{
    private: 
        std::vector <double> dblvec;
        double *dblarray;
    public:
        double *AddVecElem(int index){return &dblvec[index];} //Fine
        double *AddVecElem(int index) const {return &dblvec[index];} //compiler error "Return value type does not match function type"
        double *AddArrElem(int index){return &dblarray[index];}//Fine
        double *AddArrElem(int index) const {return &dblarray[index];}//Fine
};

Толькослучай, когда возвращение адреса адреса векторного элемента в виде функции const приводит к ошибке компилятора.

Почему это так?Как возврат адреса векторного элемента может повлиять на состояние объекта?

Ответы [ 2 ]

0 голосов
/ 29 сентября 2018

Если вы объявили функцию как функцию класса const, это означает, что вы не можете изменить переменные класса из функции, вы не можете вернуть адрес переменной класса, если только вы не пообещаете, что эта функция возвращает неизменяемое (постоянное) значение.

Внутри функции const функция рассматривает переменные класса как const переменные, поэтому, когда вы пытаетесь вернуть адрес, вы на самом деле возвращаете const double *, а не double * как требуется для функции.

Решение для этого случая - вернуть указатель на const T:

const double* AddVecElem(int index) const {return &dblvec[index];}

Или, как вы упомянули, объявить эту функцию неконстантнойfunction.

Другое решение - вернуть значение без указателя (копию значения) и использовать функцию void setValue(..) для изменения переменных данных этого класса.

Что касается double *dblarray yourФункция не возвращает сам указатель, она возвращает копию вашей переменной (обратите внимание - ваша функция возвращает double*, а переменная находится в пределах того же уровня указателя - поэтому она возвращаеткопия).Это похоже на следующий пример:

private:
    int value;
public:
    int return_value() const {
        return value; // Copy of the const returns - you don't change class's variable data
    }
    int* return_pointer_value() const {
        return &value; // Compiler error - expected int* returns const int*
    }

Итак, если вы хотите, чтобы ситуация с указателем равнялась ситуации с вектором, вы должны вернуть double**, а не double*:

double **AddArrElem(int index) const {
    return &dblarray; // Compiler error - expected double** returns const double *const*
    // (*const)=> for 'dblarray', (*)=> for '&'
}

Тогда почему вектор ведет себя иначе?Почему вы не можете вернуть & dblvec [index]?Как упоминалось в посте @ t.niese, вызов операторной функции vector распознает, что это вектор const, поэтому он автоматически возвращает const double - давайте посмотрим на эту функцию:

double& AddVecElem(int index) const {
    return dblvec[index]; // Compiler error - Expected double returns const double
}

Мыхочу вернуть ссылку на эту переменную, но возвращаемая переменная является константой.Поэтому, когда вы хотите вернуть double*, вы на самом деле возвращаете const double*.

Даже когда вы пытаетесь обойти и вызвать vector.data (), он возвращает вам const double * вместо double* - Ив этом разница между вектором и указателем.

Как ссылка: Может ли функция-член const вернуть неконстантный указатель на элемент данных?

0 голосов
/ 29 сентября 2018

Поскольку dblvec[index] в функции const будет вызывать:

const_reference operator[]( size_type pos ) const;

И с этого момента &dblarray[index] имеет тип const double *, и его нельзя преобразовать в double *.

dblarray[index] с другой стороны, это double, поэтому вы возвращаете double *

Проверьте вопрос Что может изменить метод const? дляподробнее о том, что такое const, если вы находитесь внутри функции const.

...