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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 28, средняя оценка - 5.00
Bers
Заблокирован
#1

Модификатор const в аргументах функций - C++

19.07.2011, 22:29. Просмотров 3595. Ответов 31
Метки нет (Все метки)

Постоянно путаюсь в этих константах. Как писать грамотнее?

Вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
     template<typename TypeT>  
void TLinePointer<TypeT>::operator = (TypeT* pObject)  //функция не меняет аргумент
{                               //по идее, просится const
    if(pObject==0) { Release(); return; }
    if(mp_Pointer != pObject)  
    {  
        Release();
        mp_Pointer = pObject; 
        mp_CounterLink=new int; 
        *mp_CounterLink=1;
        pObject=0; 
    }
}
Или вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
     template<typename TypeT>  
void TLinePointer<TypeT>::operator = (const TypeT* pObject) 
{
    if(pObject==0) { Release(); return; }
    if(mp_Pointer != pObject)  
    {  
        Release();
        TypeT* TempPointer = const_cast<TypeT*>(pObject); 
                                                      //приходится кастовать, потому что
        mp_Pointer = TempPointer;      //нельзя неконстантному указателю 
                                                      //присвоить константный напрямую
        mp_CounterLink=new int; 
        *mp_CounterLink=1;
        pObject=0; 
    }
}
Интуиция мне подсказывает, что второй вариант более правильный (хотя и приходиться совершать больше движений)

А что подскажут уважаемые эксперты? Или может быть есть ещё какие то варианты?
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.07.2011, 22:29
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Модификатор const в аргументах функций (C++):

Модификатор const для параметра функции не const? - C++
void foo(const int N) { int Arr; //&lt;-- ??? } В clang это работает. В VisualStudio 2015 нет.

Const-параметры в аргументах функции - C++
А тут уже const излишен, перебор. Добавлено через 3 минуты void setDescription(const std::string&amp; _description) { m_description...

Модификатор доступа const - C++
Здравсвуйте, прошу помочь с вопросом. В общем имеется такой класс: class Animator : public sf::Drawable { private: ...

Модификатор const Очередные грабли с++? - C++
Представленный ниже код не компилируется. В чем здесь может быть проблема? class CFirst { public: int GetValue() { return...

Чисто виртуальные классы. Модификатор const - C++
Приветствую всех! Известно, что чисто виртуальный (абстрактный) класс можно получить class A { public: virtual void test()=0; };...

Модификатор const в качестве возвращаемого значения - C++
const int get_size(const int&amp; a) { return a; } int main() { const int size = get_size(5);

31
Bers
Заблокирован
20.07.2011, 07:32  [ТС] #16
Цитата Сообщение от accept Посмотреть сообщение
если mp_Pointer указывает на меняемые данные, то тогда непонятно, почему адрес неизменных данных копируется в переменную-указатель, используемую для изменения данных
Суть в том, что извне приходит адрес объекта. И с этим объектом ничего не должно случиться.
mp_Pointer лишь хранит этот адрес. и все. Больше ничего не делает.

Более того, объект класса может избавиться от объекта (обнулить свой mp_Pointer)
Но это никак не должно коснуться того объекта, чей адрес помнит mp_Pointer


Если туманно и не понятно, я могу выложить больше инфы и кода. Я просто не хочу напрягать читателей обилием букв и кода

Добавлено через 4 минуты
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Этот запрет делается опять возвратом const...
Я всесторонне изучу этот момент...
Правда я не понимаю, для чего, что бы запретить действие возвращать нечто в виде константы?
По моему, проще просто запретить...
0
accept
4823 / 3244 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.07.2011, 07:42 #17
Цитата Сообщение от Bers
mp_Pointer лишь хранит этот адрес
я так понял, что он в классе
если через него не меняются данные, то он должен указывать на const

Цитата Сообщение от Bers
Более того, объект класса может избавиться от объекта (обнулить свой mp_Pointer)
сам указатель не const

C++
1
const TypeT *TempPointer;
C++
1
const TypeT *const TempPointer;
знаешь разницу ?
1
An1ka
65 / 70 / 2
Регистрация: 30.06.2011
Сообщений: 176
20.07.2011, 07:47 #18
Цитата Сообщение от Bers Посмотреть сообщение
Более того, объект класса может избавиться от объекта (обнулить свой mp_Pointer)
Но это никак не должно коснуться того объекта, чей адрес помнит mp_Pointer
Тогда объявите указатель на константу
C++
1
const TypeT *TempPointer;
Здесь сам указатель можно менять, но не данные, на которые он указывает.
C++
1
TypeT * const TempPointer;
А вот здесь всё наоборот, указатель нельзя менять, но можно менять данные на которые он указывает
1
Bers
Заблокирован
20.07.2011, 07:57  [ТС] #19
Цитата Сообщение от accept Посмотреть сообщение
я так понял, что он в классе
если через него не меняются данные, то он должен указывать на const

1. Он никак не изменяет состояние объекта о котором "помнит".
Но он может к примеру "забыть все". Объект от этого никак не пострадает, просто mp_Pointer обнулиться. Тобишь, mp_Pointer так же гарантированно используется исключительно для чтения, либо обнуляется. Это гарантирует программист.

2. Да

Добавлено через 4 минуты
An1ka, милая, вы не поняли о чём речь.
0
accept
4823 / 3244 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.07.2011, 07:57 #20
Цитата Сообщение от Bers
Тобишь, mp_Pointer так же гарантированно используется исключительно для чтения
таким образом он должен указывать на const

C++
1
const TypeT *mp_Pointer;
это где-то сверху должно быть
имя типа TypeT должно быть там известно
1
Bers
Заблокирован
20.07.2011, 08:07  [ТС] #21
Цитата Сообщение от accept Посмотреть сообщение
таким образом он должен указывать на const
Но он может обнулиться!

Он гарантирует, что ничего не сделает с содержимом того, на что указывает.
Но с самим собой он может делать что угодно!

Добавлено через 7 минут
Цитата Сообщение от accept Посмотреть сообщение
это где-то сверху должно быть
имя типа TypeT должно быть там известно
Нет, ибо данная переменная "перемена" по задумке и логике.
0
Kastaneda
Нарушитель
Эксперт С++
4676 / 2880 / 234
Регистрация: 12.12.2009
Сообщений: 7,314
Записей в блоге: 2
Завершенные тесты: 1
20.07.2011, 08:23 #22
Цитата Сообщение от Bers Посмотреть сообщение
Но он может обнулиться!
Ну тут проблема была бы если бы указатель был const (а не то, на что он указывает).
Вот абсолютно нормальный код:
C++
1
2
3
4
5
6
        int a=10;
    const int* ptr;
    ptr=&a;
    std::cout<<ptr<<std::endl;
    ptr=NULL;
    std::cout<<ptr<<std::endl;
1
accept
4823 / 3244 / 165
Регистрация: 10.12.2008
Сообщений: 10,682
20.07.2011, 08:45 #23
Цитата Сообщение от Bers
Но он может обнулиться!

Он гарантирует, что ничего не сделает с содержимом того, на что указывает.
Но с самим собой он может делать что угодно!
Цитата Сообщение от Bers
2. Да
похоже, что нет

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

Добавлено через 9 минут
C
1
2
3
4
    char c = 'a';
    const char cc = 'b';
 
    c = cc;
это правильно

C
1
2
3
4
5
6
7
    char c = 'a';
    char *pc;
    const char *cpc;
 
    pc = &c;
    cpc = &c;
    pc = cpc;
это неправильно

Код
[guest@localhost tests]$ .ansi t.c -o t
t.c: В функции ‘main’:
t.c:12:8: предупреждение: присваивание отменяет квалификаторы указуемого типа
[guest@localhost tests]$
1
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
20.07.2011, 08:56 #24
Цитата Сообщение от Bers Посмотреть сообщение
/приходится кастовать, потому что //нельзя неконстантному указателю //присвоить константный напрямую
Цитата Сообщение от Bers Посмотреть сообщение
Однако! Попандос. Присвоить неконстрантному указателю значение константного нельзя
Не стоит путать константный указатель и указатель на константу.

Цитата Сообщение от Bers Посмотреть сообщение
TypeT* TempPointer = const_cast<TypeT*>(pObject);
Можно заменить на
C++
1
const TypeT * temp = pObject;
Цитата Сообщение от Bers Посмотреть сообщение
Что делать?
Я для себя давно уже решил и использую принцип максимальным ограничений. Всё что может быть private делается private. Всё что может быть const делается константным. Компилятору всё равно, а мне жить проще. Множество потенциальных ошибок просто невозможно совершить.

А вообще, почитай, что значит вот это:
C++
1
2
3
const int * a;
int * const b;
const int * const c;
Итого: Ничего плохого в const быть не может. Плохое может быть в const_cast, но его (плохого) может в нём и не быть.
1
xAtom
915 / 740 / 60
Регистрация: 09.12.2010
Сообщений: 1,346
Записей в блоге: 1
20.07.2011, 18:47 #25
Цитата Сообщение от Deviaphan Посмотреть сообщение
Плохое может быть в const_cast, но его (плохого) может в нём и не быть
Само приведение типа, может повлиять на данные, вот пример .
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
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
 
 
void _str1(char* s) {
   while( *s )
      *s++ = 'A';
}
 
 
void _str2(const char* s) {
   char* c = (char*) s;
   while( *c )
      *c++ = 'B';
}
 
 
void _str3(char* const s) {
   char* c = (char*) s;
    while( *c )
      *c++ = 'C';
}
 
 
void _str4(const char* const s) {
    char* c = (char*) s;
    while( *c )
      *c++ = 'D';
}
 
 
 
int main(void)
{
   char s[] =  "address ptr";
 
   puts(s);
 
   _str1(s);
   puts(s);
 
   _str2(s);
   puts(s);
 
   _str3(s);
   puts(s);
 
   _str4(s);
   puts(s);
 
 
   getchar();
   return 0;
}
1
Bers
Заблокирован
20.07.2011, 19:51  [ТС] #26
Ну все, вразумел вроде бы. Блин... даже и не подумал бы, что столько нюансов может быть с этой константностью.

Моя идея о том, что константа - это "переменная" ONLY READ рассыпается на куски....
А жаль.... Ещё совсем вчера было намного проще жить в этом мире.

Последний вопрос:
Допустим мой Потребитель "запоминает" где живёт его Менеджер.
Внутри класса Потребителя находится указатель на объект класса Менеджера.
Поскольку внутри Потребителя никогда не будут происходить операции типа:
delete pМенеджер; pМенеджер = NULL;

Более того - и не должны происходить!
То указатель на менеджера можно (а значит и нужно) сделать константным.
Это будит означать, что Потребитель не отвечает, за время жизни своего Менеджера. И Ничего не может сделать с той областью памяти, где этот Менеджер живёт (не может его убить).

Я все правильно понял?
0
Evg
Эксперт CАвтор FAQ
18036 / 6268 / 428
Регистрация: 30.03.2009
Сообщений: 17,244
Записей в блоге: 28
20.07.2011, 20:00 #27
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Bers, не видя всего исходника целиком сложно понять, чего конерктно ты не понимаешь или понимаешь, но не правильно. На всякий случай почитай тут Неочевидные ответы на простые вопросы раздел 4, лишним не будет

Добавлено через 27 секунд
Цитата Сообщение от xAtom Посмотреть сообщение
Само приведение типа, может повлиять на данные, вот пример
Только при этом программист - сам дурак
3
Deviaphan
Делаю внезапно и красиво
Эксперт С++
1305 / 1220 / 50
Регистрация: 22.03.2011
Сообщений: 3,744
20.07.2011, 20:02 #28
Константный указатель - это указатель на область памяти, которому нельзя присвоить указатель на другую область памяти.
Указатель на константу - это указатель на область памяти, которую нельзя изменить через этот указатель.
Константный указатель на константу - оба этих ограничения.
1
Evg
Эксперт CАвтор FAQ
18036 / 6268 / 428
Регистрация: 30.03.2009
Сообщений: 17,244
Записей в блоге: 28
20.07.2011, 20:08 #29
Цитата Сообщение от Deviaphan Посмотреть сообщение
Константный указатель - это указатель на область памяти, которому нельзя присвоить указатель на другую область памяти.
Указатель на константу - это указатель на область памяти, которую нельзя изменить через этот указатель.
Константный указатель на константу - оба этих ограничения.
Причём надо понимать, что "нельзя" в обоих случаях означает "нельзя в языке программирования". И в подавляющем большинстве случаев это означает "если очень хочется, то можно, но компилятор за последствия не отвечает". А в оставшихся случаях это действительно "нельзя", потому что тебе это не даст сделать операционная система или даже аппаратура
1
Bers
Заблокирован
20.07.2011, 20:24  [ТС] #30
У меня была путаница в голове, я думал что константный указатель указывает собственно на константу, а не то, что он сам по себе является константой.

Теорию проштудировал, ошибку осознал.

Если и остались ещё какие то неясности - думаю практика это исправит.

Всем огромное спасибо за участие.
Думаю, что тему можно закрыть.
0
20.07.2011, 20:24
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2011, 20:24
Привет! Вот еще темы с ответами:

int const * const foo(const int* param) const - разъясните значение квалификаторов - C++
int const * const foo(const int* param) const -----1------2----------3----------------4 1: ? 2: делает содержимое массива или...

В чем различия константных объектов и константных ссылок на объекты в аргументах функций-членов? - C++
Как правильно необходимо указывать типы данных для входных параметров метода? Пример: void resetArguments(const int inputStrong,...

Хочу разобраться с прототипами функций, const но переменная изменяется - C++
Оригиналы хэш функций тут - назовем это ENG статьёй Я так подозреваю написано это на С, но вполне без изменений запустится на С++ ...

char operator[](unsigned short offset) const; // что означает const? - C++
Собстенно вопрос уже озвучен :).


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

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru