Форум программистов, компьютерный форум CyberForum.ru

Константные функции-члены класса, возвращающие ссылку на константу - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 56, средняя оценка - 4.66
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
08.08.2011, 21:09     Константные функции-члены класса, возвращающие ссылку на константу #1
Упражняюсь по книге Липпмана, выполняю задания по теме классы.
Необходимо реализовать класс person, который способен хранить имя и адрес человека, а также создать функции, возвращающие при обращении имя и адрес.
Вопрос, который ставит автор книги: "Должны ли эти функции быть константными? Объясните почему."
Вот тут я начал путаться. Вот моя реализация:
файл person.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef PERSON_H_
#define PERSON_H_
 
class person {
public:
    //конструктор, принимающий две строки типа string
    person( std::string &_name, std::string &_addres ) :
        name( _name ), addres( _addres ) {
    }
    //метод, возвращающий addres
    const std::string &get_addres() const {
        return addres;
    }
    //метод, возвращающий name
    const std::string &get_name() const {
        return name;
    }
 
private:
    //поле для хранения имени
    std::string name;
    //поле для хранения адреса
    std::string addres;
};
 
#endif /* PERSON_H_ */
Для тестирования класса, файл test_class_person.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include "person.h"
using namespace std;
 
int main() {
    string str1 = "Alexander";
    string str2 = "Zelenogradsk";
    person pers( str1, str2 );
    cout << pers.get_name() << " " << pers.get_addres() << endl;
    
    string str3 = pers.get_name();
    str3 += "222";
    cout << str3 << " " << pers.get_name();
    return 0;
}
Я решил так
1) Константными эти функции должны быть, так как они не меняют значений переменных-членов объекта.
2) Возвращать они должны лишь константную ссылку на строку, а не просто тип string, дабы избежать ненужного копирования.
Прав ли я? Если нет, то объясните почему.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.08.2011, 21:09     Константные функции-члены класса, возвращающие ссылку на константу
Посмотрите здесь:

C++ Константные статические объекты класса.
класс «Строка» (данные-члены класса – строчка, функции-члены класса – операции) C++
C++ Константные функции-члены ?
константные поля класса C++
Почему нехорошо себя ведёт конструктор класса (не компилится ничё), если ему параметром ссылку на константу? C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
09.08.2011, 18:51  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #21
2 Deviaphan - Спасибо за демонстрацию, повторное использование действительно невозможно и сделать &sss ссылкой на не константную переменную тоже невозможно.

Если изменить методы класса person так:

C++
1
2
3
4
5
6
7
8
9
10
...
//метод, возвращающий addres
    std::string get_addres() const {
        return addres;
    }
    //метод, возвращающий name
    std::string get_name() const {
        return name;
    }
...
То такие варианты использования уже невозможны:
C++
1
const string &sss = ( person( str1, str2 ).get_name() );
C++
1
string &sss = ( person( str1, str2 ).get_name() );
А вот такие варианты уже возможны:
C++
1
const string sss = ( person( str1, str2 ).get_name() );
C++
1
2
string sss = ( person( str1, str2 ).get_name() );
sss += str2;
Насколько я понял, вариант, когда методы класса возвращают не ссылку, а объект - предпочтителен, так как более защищен от возникновения ошибок. Deviaphan, я правильно понял твою демонстрацию?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
09.08.2011, 18:59     Константные функции-члены класса, возвращающие ссылку на константу #22
Цитата Сообщение от Roof Посмотреть сообщение
я правильно понял твою демонстрацию?
Правильно.
Но я предпочитаю возвращать константную ссылку для сложных объектов (в том числе и строк), но не использую потенциально опасные конструкции (как в примере). Объекты, локальные для строки кода нужно использовать очень аккуратно и лучше вообще их не использовать, пока не поймёшь до конца принцип их работы и время жизни этих объектов.

Т.е. лучше возвращать константную ссылку, но использовать код вида:
C++
1
2
Person temp( str1, str2 );
const string &sss = temp.get_name();
PointsEqual
ниначмуроФ
 Аватар для PointsEqual
832 / 516 / 33
Регистрация: 12.10.2009
Сообщений: 1,915
09.08.2011, 19:26     Константные функции-члены класса, возвращающие ссылку на константу #23
Цитата Сообщение от Roof Посмотреть сообщение
Насколько я понял, вариант, когда методы класса возвращают не ссылку, а объект - предпочтителен

Не по теме:

наконет-то свершилось

Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
09.08.2011, 22:01  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #24
Цитата Сообщение от Deviaphan Посмотреть сообщение
Но я предпочитаю возвращать константную ссылку для сложных объектов (в том числе и строк)
Вот и я думаю, что константную ссылку на объект возвращать продуктивней, дабы избежать копирования. Но опять же, PointsEqual рекомендует возвращать сам объект, дабы избежать возможности возникновения указанных выше ошибок, которые могут возникнуть при использовании моего класса.

Однозначного ответа, как я понимаю тут нет.
Из всего сказанного я сделал такие выводы:
- можно возвращать константную ссылку на объект, надеясь на то, что пользователь моего класса не будет писать подобные инструкции:
C++
1
const string & sss = ( person( str1, str2 ).get_name() );
- можно возвращать сам объект, пренебрегая копированием, но не боясь приведенных выше ошибок.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
09.08.2011, 23:11     Константные функции-члены класса, возвращающие ссылку на константу #25
Roof, однозначно PointsEqual правильно говорит. Ссылка действительно может пережить свой объект. Так, что, возвращайте строку, а не ссылку.
alex_x_x
бжни
 Аватар для alex_x_x
2441 / 1646 / 84
Регистрация: 14.05.2009
Сообщений: 7,163
09.08.2011, 23:29     Константные функции-члены класса, возвращающие ссылку на константу #26
кроме того к вопросу о копировании - в продвинутых библиотеках (в Qt точно знаю, полагаю, что так сделано и в многих реализациях stl) контейнеры реализуют идиому "письмо - конверт" (манипулятор/тело), обеспечивающую эффективные операции копирования - фактически применение принципа копирования при записи
это я к тому, что зная, что операции копирования контейнеров растратные, нужно учитывать, что они могут быть много хитрее и на самом деле не приводить к выделению памяти и копированию данных
и не пренебрегать безопасностью
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
09.08.2011, 23:59  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #27
easybudda, alex_x_x - спасибо за ответы, очень помогли.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
10.08.2011, 00:30     Константные функции-члены класса, возвращающие ссылку на константу #28
На самом деле всё хитрее...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
 
class person {
public:
        //конструктор, принимающий две строки типа string
        person( const std::string &_name, const std::string &_address ) :
                name( _name ), address( _address ) {
        }
        //метод, возвращающий addres
        const std::string &get_address() const {
                return address;
        }
        //метод, возвращающий name
        const std::string &get_name() const {
                return name;
        }
        void set_name(const std::string & _name) { 
            name = _name; 
        }
        void set_address(const std::string & _address) { 
            address = _address; 
        }
 
private:
        //поле для хранения имени
        std::string name;
        //поле для хранения адреса
        std::string address;
};
 
int main(){
    person p("Vasya", "Hell");
    
    const char * n = p.get_name().c_str();
    std::cout << n << std::endl;
    p.set_name("Petya");
    std::cout << n << std::endl;
    
    return 0;
}
Два раза выведет Васю. Думаю, функции get_name, get_address (кстати, это слово с двумя s пишется) на самом деле создают константные копии строк, ссылки на которые и возвращают. Сэкономить в любом случае не получится, морока одна. Возвращайте строки.
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
10.08.2011, 06:27  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #29
2 easybudda,
Цитата Сообщение от easybudda Посмотреть сообщение
Думаю, функции get_name, get_address (кстати, это слово с двумя s пишется) на самом деле создают константные копии строк, ссылки на которые и возвращают. Сэкономить в любом случае не получится, морока одна. Возвращайте строки.
Об этом не догадывался, большое спасибо за информацию.
Однозначно - буду возвращать строку, а не ссылку.

Но мне не понятен смысл Вашего примера. Вот как я его понял:
Методы get_name() и get_address() возвращают ссылку на константу, как в Вашем примере.
C++
1
2
3
4
5
6
7
8
...
person p("Vasya", "Hell");
 
const char * n = p.get_name().c_str();  //строка n в стиле C инициализирована строкой "Vasya"
std::cout << n << std::endl; //вывели n
p.set_name("Petya");    //никакого отношения к n не имеет
std::cout << n << std::endl; //снова вывели n
...
В Вашем примере выводится два раза Vasya. Как я понимаю - это логично, ведь n инициализирована вначале, потом хоть сколько меняй состояние объекта p - на n это никак не отразится.

Также два раза выведется Vasya, если методы get_name() и get_address() будут возвращать константные строки или просто строки. Соответственно объявление и инициализацию переменной n я проводил так:
C++
1
const std::string n = p.get_name();
или
C++
1
std::string n = p.get_name();
А возвращать string или const string, насколько я понял нет никакой разницы.

Т.е. осталось понять, что именно Вы хотели сказать в Вашем примере.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
10.08.2011, 09:54     Константные функции-члены класса, возвращающие ссылку на константу #30
Цитата Сообщение от Roof Посмотреть сообщение
А возвращать string или const string, насколько я понял нет никакой разницы.
В С функции не должны возвращать константные значения. На счёт С++ не знаю, но в принципе как-то не за чем... К примеру, если есть фукнция, переводящая строку в верхний регистр, то вот такая конструкция с константной строкой скорее всего не будет работать
C++
1
std::cout << stringToUppercase(some_person.get_name()) << std::endl;
CyBOSSeR
Эксперт C++
 Аватар для CyBOSSeR
2293 / 1663 / 86
Регистрация: 06.03.2009
Сообщений: 3,675
10.08.2011, 10:30     Константные функции-члены класса, возвращающие ссылку на константу #31
Цитата Сообщение от Deviaphan Посмотреть сообщение
Но я предпочитаю возвращать константную ссылку для сложных объектов
В таких случаях умные указатели предпочтительнее, возвращать ссылки - слишком потенциально опасное действие, чтобы его производить.
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 10:40     Константные функции-члены класса, возвращающие ссылку на константу #32
умные указатели предпочтительнее
Абсолютно да!
Но чтобы возвращать умные указатели на внутренние данные объекта, эти данные должны быть умными указателями. Что не всегда желательно и возможно.
С другой стороны, С++ вообще очень потенциально опасный язык и речь должна идти о культуре программирования и опыте программиста. Когда пишешь простой и понятный код, опасные конструкции встречаются гораздо реже.
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
10.08.2011, 15:22  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #33
Спасибо всем ответившим. На свой вопрос получил однозначный ответ.
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
10.08.2011, 15:42     Константные функции-члены класса, возвращающие ссылку на константу #34
Roof, ну и в заключении поясню суть своего примера: я его дома на ноуте с debian делал, там, напомню, два раза Vasya вывелось. А вот, как этот же самый код (отсюда скопировал) с другими компиляторами работает:
Константные функции-члены класса, возвращающие ссылку на константу
Константные функции-члены класса, возвращающие ссылку на константу
Можно долго гадать, или разбираться, почему оно так, но лучше просто не оставлять такие вещи на откуп компилятору...
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 15:50     Константные функции-члены класса, возвращающие ссылку на константу #35
Цитата Сообщение от easybudda Посмотреть сообщение
почему оно так
Второй раз не Вася вывелся, а Вас(стрелочка).
lavan
51 / 51 / 1
Регистрация: 21.03.2009
Сообщений: 371
10.08.2011, 16:03     Константные функции-члены класса, возвращающие ссылку на константу #36
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<iostream>
#include<string>
using namespace std;
class A {
private:
string str;
public:
    A();
    string & fun();
    void show(){
     cout<<str;
    }
};
int main() {
  A obj;
  obj.show();
  obj.fun()="kol";//изменили str
  cout<<endl;
  obj.show();
  cin.get();
  return 0;
}
A::A(){
str="gflj";
}
string & A::fun(){
return str;
}
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
10.08.2011, 16:04     Константные функции-члены класса, возвращающие ссылку на константу #37
Цитата Сообщение от Deviaphan Посмотреть сообщение
Второй раз не Вася вывелся, а Вас(стрелочка).
Да, я заметил. В cygwin указатель указывает на буфер строки, которая к моменту второго обращения уже не существует. Мелкомягкий каким-то чудом сохраняет указатель, хоть она к тому времени и поменялась (на сколько знаю, оператор = должен бы уничтожать старую строку и создавать новую), а вот в BSD снова два Васи и без стрелок:
Константные функции-члены класса, возвращающие ссылку на константу
Deviaphan
Делаю внезапно и красиво
Эксперт C++
 Аватар для Deviaphan
1283 / 1217 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
10.08.2011, 16:08     Константные функции-члены класса, возвращающие ссылку на константу #38
Цитата Сообщение от easybudda Посмотреть сообщение
Мелкомягкий каким-то чудом сохраняет указатель
Не исключено, что была создана копия строки, в целях оптимизации. Насколько я помню, короткие строки хранятся в массиве в самом объекте, без выделения памяти. А раз обещался const компилятор мог создать копию. Поэтому изменив оригинальный объект осталась строка в копии... А вообще, чего гадать на ошибках, лучше так не писать и усё.)
easybudda
Модератор
Эксперт С++
 Аватар для easybudda
9372 / 5422 / 914
Регистрация: 25.07.2009
Сообщений: 10,423
10.08.2011, 16:25     Константные функции-члены класса, возвращающие ссылку на константу #39
Цитата Сообщение от Deviaphan Посмотреть сообщение
Поэтому изменив оригинальный объект осталась строка в копии...
Так в том и прикол, что мелкомягкий не создавал копии, просто вернул указатель на массив char* от строки-члена класса, который сохранился после присвоения строке другого значения, скорее всего по причине
Цитата Сообщение от Deviaphan Посмотреть сообщение
короткие строки хранятся в массиве в самом объекте, без выделения памяти
А вот про это
Цитата Сообщение от Deviaphan Посмотреть сообщение
лучше так не писать
я собственно и говорил.

Цитата Сообщение от lavan Посмотреть сообщение
Возврат const string & необходим чтобы избежать возможности изменять private часть класса без использования интерфейса
Спасибо, Кэп, разобрались уже...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.08.2011, 17:56     Константные функции-члены класса, возвращающие ссылку на константу
Еще ссылки по теме:

Константные методы и объекты класса C++
Константные функции-члены C++
Где инициализировать константные данные класса? C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Roof
 Аватар для Roof
154 / 154 / 10
Регистрация: 03.11.2010
Сообщений: 393
10.08.2011, 17:56  [ТС]     Константные функции-члены класса, возвращающие ссылку на константу #40
2 easybudda - я все примеры тестирую на Ubuntu с g++ и Ваш пример у меня вывел два раза Vasya, как и у Вас на Debain и BSD.

Цитата Сообщение от easybudda Посмотреть сообщение
Можно долго гадать, или разбираться, почему оно так, но лучше просто не оставлять такие вещи на откуп компилятору...
- с этим полностью согласен.
Yandex
Объявления
10.08.2011, 17:56     Константные функции-члены класса, возвращающие ссылку на константу
Ответ Создать тему
Опции темы

Текущее время: 19:52. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru