Почему полезно сделать функцию const? - PullRequest
3 голосов
/ 24 декабря 2010

Почему так полезно сделать функцию const, если вы можете только читать переменные, но не писать (переменная класса)?

Ответы [ 6 ]

3 голосов
/ 24 декабря 2010

Если вы передаете что-то еще const-указатель или константную ссылку на экземпляр вашего класса, тогда он может вызывать только const-методы класса (если есть).

Очевидно, если вы никогда не беспокоитесь о правильности constс вашими типами вы можете игнорировать это.

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

3 голосов
/ 24 декабря 2010

Чтобы вы не «случайно» изменили одну из переменных класса. Это просто мера безопасности.

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

1 голос
/ 24 декабря 2010

Одна причина в том, что const - это вирус.Это означает, что если часть кода является const-правильной, то остальная часть кода не будет взаимодействовать с этой частью.

Если вы игнорируете const-правильность, шансы ваших классов работают рука об рукус другими библиотеками (начиная со стандартной библиотеки) тонкие.

Например:

#include <vector>
#include <algorithm>

struct X
{
    int n;
    bool operator< (X b)
    { 
        return n < b.n;
    }
};

int main()
{
    std::vector<X> vec;
    std::sort(vec.begin(), vec.end());
}

С codepad.org

In function 'const _Tp& std::__median(const _Tp&, const _Tp&, const _Tp&) [with _Tp = X]':
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2642:   instantiated from 'void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >, _Size = int]'
/usr/local/lib/gcc/i686-pc-linux-gnu/4.1.2/../../../../include/c++/4.1.2/bits/stl_algo.h:2713:   instantiated from 'void std::sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<X*, __gnu_norm::vector<X, std::allocator<X> > >, __gnu_debug_def::vector<X, std::allocator<X> > >]'
t.cpp:17:   instantiated from here
Line 90: error: no match for 'operator<' in '__a < __b'

Оператор сравнения, совместимый с stdlib, должендать обещание, что аргументы не изменены.Если бы объекты на самом деле изменялись во время их сравнения, попытка их сортировки была бы довольно бесполезной.

Другой пример: вы не сможете передавать аргументы по константной ссылке, что является традиционным способом передачи большихобъекты.Вместо этого вам придется передавать аргументы по изменяемым ссылкам.Теперь вы не сможете передавать временные функции в ваши функции.

0 голосов
/ 24 декабря 2010

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

0 голосов
/ 24 декабря 2010

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

0 голосов
/ 24 декабря 2010

Если у вас есть объект const, он позволяет только функциям-членам const работать с ним.

...