Зачем нужны как ссылка const, так и функция-член const? - PullRequest
2 голосов
/ 17 июня 2020

Я выполняю упражнения из «Принципы программирования и практика с использованием C ++», и я нашел класс с этой функцией-членом здесь :

const vector<string> &get_name() const { return name; }

, где name - вектор: vector< string> name;

На данный момент в книге представлены 2 концепции (вплоть до страницы 235):

  1. возвращает константную ссылку, чтобы функция не изменяла возвращаемое значение:

    const vector<string> &get_name() { return name; } 
    
  2. константная функция-член, которая не может изменять объект. в этом случае это будет примерно так:

    vector<string> get_name() const { return name; } 
    

Может быть, я не совсем понимаю, но разве эти две концепции не совпадают? Не хочу менять вектор "name".

Зачем нужны оба "const"?

Спасибо всем, кто нашел время ответить!

Ответы [ 3 ]

2 голосов
/ 17 июня 2020
  1. возвращает константную ссылку, чтобы функция не изменяла возвращаемое значение
  2. константная функция-член, которая не может изменять объект. в данном случае это будет примерно так

Это могло быть немного яснее, я попробую объяснить это лучше.

Возвращение константы ссылка предотвращает изменение возвращаемого объекта вызывающими .

Вот пример:

// let get_name be `const std::vector<std::string>& get_name()`

np1.get_name().size(); // ok, size is a const function of vector
np1.get_name().push_back("hello"); // ERROR! push_back is not a const function of vector

Так что действительно, вызывающий не может изменить name вектор. Тип возвращаемого значения имеет квалификацию const.

Однако, если функция get_name сама не квалифицируется как const (не тип возвращаемого значения), тогда разрешается изменять имя из самого класса.

Видите ли, функции-члены получают скрытый this параметр, который является указателем на вызываемый объект. Указатель может указывать либо на константный объект, либо на изменяемый объект. Вот сравнение:

// returning const ref, callers cannot change the name vector
const std::vector<std::string>& get_name() {
    // The function receive a `this` that points to a mutable,
    // we can change the name from the inside
    this->name.push_back("another");
    return name;
}

// the `this` pointer points to const -----v---v
const std::vector<std::string>& get_name() const {
    this->name.push_back("another"); // ERROR! Cannot mutate member of const object
    return name;
}

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

Например , вы не только знаете, что функция vector::size() не изменяет вектор, но и компилятор гарантирует это, поскольку это функция-член с квалификацией const.

И последний бит, код, который вы разместили здесь:

vector<string> get_name() const { return name; } 

Ссылка не будет возвращена, но будет сделана копия. Вызывающий может изменять копию как угодно, но не может изменять name саму.

Вот пример мутированной копии:

auto name_copy = np1.get_name();

name_copy.push_back("another name"); // works, we mutated the copy by adding an element
1 голос
/ 17 июня 2020

Функция-член имеет неявную this -ссылку.

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

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

0 голосов
/ 17 июня 2020

В этом случае возвращается константная ссылка на vector<string>, и мы не можем изменить этот вектор. Но мы можем изменить vector<string> name в этой функции.

const vector<string> &get_name() { return name; } 

В этом случае вернуть копию vector<string>, и мы можем изменить этот вектор, потому что это уже другой вектор. В этой функции мы не можем изменить vector<string> name.

vector<string> get_name() const { return name; } 
...