Какое определение для const-правильности? - PullRequest
5 голосов
/ 26 ноября 2011

Я думал, что понятие «правильности констант» было довольно хорошо определено, но когда я говорил об этом с другими людьми, казалось, что у нас были разные представления о том, что это значит.Некоторые люди говорят, что это программа с аннотациями «const» в максимально возможном количестве мест.Другие определяют программу как const-правильную, если и только если нет никаких нарушений constness, где используется константная аннотация (т. Е. Это свойство, которое проверяет компилятор для вас).

Так что я бы хотелзнать, какие из этих функций являются правильными:

struct Person {
    string getName1() const { return _name; }
    string getName2() { return _name; }
    string getName3() const { _name = "John"; return _name; }
    string getName4() { _name = "John"; return _name; }

    string _name;
};

Я искал в Интернете определения, но не смог найти определенный ответ, и у меня также есть подозрения, что может быть случай цитогенез в игре.Так может ли кто-нибудь привести какую-либо убедительную цитату для определения?

Ответы [ 6 ]

7 голосов
/ 26 ноября 2011

На мой взгляд, «правильная константа» означает:

Все, что не предназначено для изменения, должно быть помечено как const.

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

Есть три основных места, где это полезно:

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

  2. «Свободные» переменные, сами локальные переменные и переменные-члены также могут быть помечены const - после инициализации они не могут быть изменены. Пример - локальная переменная:

    int f(int i) {
       const int square = i*i;
       // do something here that uses, but doesn't change square
       return square;
    }
    

    или свободная переменная:

    extern const double PI; // set somewhere else but not changed.
    

    Или переменная-член:

    class foo {
       const int state; // can't be changed once constructed
       foo(int s) : state(i) {}
    };
    
  3. Аргументы функции также могут быть помечены const, определение может соответствовать неконстантному объявлению:

    void f(int i);
    void f(const int i) {
        // the fact that i is const is an implementation detail of f here
    }
    

    В качестве примечания const в некоторых случаях требуется корректность ссылок:

    void g(const std::string& s);
    void f(std::string& s);
    

    Из этих двух можно использовать в нескольких местах:

    g("hi"); // Fine
    f("hi"); // Not fine - you can't bind a temporary to a reference
    

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

4 голосов
/ 26 ноября 2011

Текст из parashift :

Это означает использование ключевого слова const для предотвращения получения объектов const. мутировали.

1 голос
/ 26 ноября 2011

Только getName3 нарушает const-правильность, потому что _name является постоянным (в частности, const std::string &) в теле функции, а std::string::operator= является не const.

getName2 плохой дизайн, потому что он требует изменяемого контекста, даже если он не выполняет никаких мутаций, поэтому он должен быть объявлен const, так как в противном случае это привело бы к неожиданным ограничениям,то есть вы не можете вызывать его через const Person &.

Вы также можете добавить в смесь корректность «volatile» и «rvalue», которые похожи по духу.

Корректность константности может бытьчувствуется через его нелокальные эффекты.Типичными примерами являются реляционные операторы (operator< и operator==): если вы не пометите их как const, многие стандартные алгоритмы и контейнеры не будут работать с вашим классом, поскольку они обычно применяют операторы к ссылкам на константные элементы,В этом смысле отсутствие «как можно более постоянного» накладывает ненужные ограничения на использование вашего кода.С противоположной точки зрения, то же самое применимо, если ваши собственные функции излишне требуют изменяемой ссылки на объект, так как это лишит вас необходимости использовать постоянные ссылки и лишит вас проверок во время компиляции, что операция, которую вы думалибыл не мутировавшим, фактически не мутировал объект.

0 голосов
/ 26 ноября 2011

getName3 () неверно, так как меняет имя. Остальные верны.

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

0 голосов
/ 26 ноября 2011

Constкорректность - это правильное определение и определение случаев, когда методы являются изменяемыми или неизменяемыми.

Все, что не является изменяемым, должно быть помечено как const.

Подробнее о wikipedia

0 голосов
/ 26 ноября 2011

В этой главе часто задаваемых вопросов говорится только о правильности const для c ++. Процитирую это:

Это означает использование ключевого слова const для предотвращения получения объектов const. мутировали.

О функциях вашего члена:

string getName1() const { return _name; }

Это одно правильное. Он просто возвращает копию переменной-члена.

string getName2() { return _name; }

Этот код не является константным, поскольку он не объявлен константным членом.

string getName3() const { _name = "John"; return _name; }

Не константно-корректно, потому что он изменяет переменную-член в функции-члене const. Это должно привести к ошибке компиляции.

string getName4() { _name = "John"; return _name; }

Это const-правильное имя, потому что оно изменяет переменную-член.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...