Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Что дает const в описании функции (для многопоточ)


Автор: neosapient 8.11.2007, 16:15
Вот увидел в чужем коде класс с методом
Код

class SomeClass 
{
...
void Metod(int in) const;
...
};
...

void Metod(int in) const
{
...
}

Что дает для метода/функции эта приставка "const", и как соотноситься она с многопоточностью?

Автор: bsa 8.11.2007, 16:17
это означает, что данный метод не меняет поля класса.

Автор: Daevaorn 8.11.2007, 16:18
Цитата(neosapient @  8.11.2007,  17:15 Найти цитируемый пост)
Что дает для метода/функции эта приставка "const",

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

Автор: Alek86 8.11.2007, 16:22
то есть в двух потоках их можно использовать, если в классе не объявлены mutable переменные и они (функции) не используют глобальные переменные


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

Автор: archimed7592 8.11.2007, 16:34
Цитата(Alek86 @  8.11.2007,  16:22 Найти цитируемый пост)
короче говоря, гарантий с ними никаких.

Гарантии есть, если константная ф-ция детерминирована smile.

Автор: neosapient 8.11.2007, 16:41
пожалуйста, говорите более простым языком
----------
про mutable  точно не скажу
но есть класс диспетчер (в единственном экземпляре), который хранит указатели на список.
есть метод добавления и удаления элементов из списка и переход по списку. 

вот я встретил этот параметр и подумал - может каким то из моих функций присвоить "const "
посмотрите пример 
Там метод Add вызывается из одного потока, а методы GetNext и DeleteThisAndGetNext вызываются в двух потоках паралельно

Автор: archimed7592 8.11.2007, 16:46
Цитата(neosapient @  8.11.2007,  16:41 Найти цитируемый пост)
пожалуйста, говорите более простым языком

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

Автор: neosapient 8.11.2007, 16:51
Цитата(archimed7592 @  8.11.2007,  16:46 Найти цитируемый пост)
Детерминированная ф-ция - это та, результат работы которой зависит только от аргументов, ей переданных. Т.е. результат такой ф-ции не должен зависеть ни от ввода с клавиатуры, ни от глобальных переменных, ни от результата другой недетерминированной ф-ции. 

понял
----
Могут ли теряться данные в том написании класса?
ListDisp.rar http://forum.vingrad.ru/act-Attach/type/post/id-1310183.html

Автор: Dims 9.11.2007, 03:25
Надо помнить, что функция-член класса -- это обычная глобальная функция, которой в первом параметре передаётся указатель на объект класса и кладётся в переменную this. Просто синтаксис для функций-членов -- сокращённый.

Поскольку перед всеми другими указателями можно ставить const, то и перед этим должно быть можно. Но как, если он нигде не упоминается в записи? Вот и придумали, что словечко const надо ставить перед телом функции, если это определение и перед точкой с запятой, если это описание.

На многопоточность это никак не влияет. Эта фича работает на уровне компилятора, который выдаёт ошибки, если ты пытаешься изменить значение по адресу, который объявлен const. Ограничение легко обойти, как намеренно, так и случайно. 

Автор: neosapient 9.11.2007, 10:29
Спасибо, вопрос исчерпан

Автор: JackYF 9.11.2007, 13:24
Цитата(Dims @  9.11.2007,  03:25 Найти цитируемый пост)
Вот и придумали, что словечко const надо ставить перед телом функции, если это определение и перед точкой с запятой, если это описание.

Неверно. В обоих случаях const ставится после определения параметров функции.

Автор: archimed7592 9.11.2007, 13:38
Кто-нибудь когда-нибудь встречал что-нибудь вроде этого? smile
Код

struct A
{
    void foo() volatile;
    void foo() const volatile;
};


Автор: Dims 9.11.2007, 23:02
Цитата(JackYF @  9.11.2007,  13:24 Найти цитируемый пост)
Неверно. В обоих случаях const ставится после определения параметров функции. 

Девятый вагон -- это тот который после восьмого, а не тот, который перед десятым smile

Автор: JackYF 9.11.2007, 23:26
Цитата(Dims @  9.11.2007,  23:02 Найти цитируемый пост)
Девятый вагон -- это тот который после восьмого, а не тот, который перед десятым

Тьфу, да. Просто, имхо, как-то ты коряво написал, хотя, действительно, правильно smile Приношу свои извинения.

Цитата(archimed7592 @  9.11.2007,  13:38 Найти цитируемый пост)
void foo() volatile;
    void foo() const volatile;

нет :(

Автор: Alek86 10.11.2007, 11:20
извиняюсь за продолжение темы.

Цитата(archimed7592 @  8.11.2007,  16:34 Найти цитируемый пост)
Гарантии есть, если константная ф-ция детерминирована


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

Автор: archimed7592 10.11.2007, 12:09
Цитата(Alek86 @  10.11.2007,  11:20 Найти цитируемый пост)
если спрашивалось что-то типа, могу ли я ее безбоязненно использовать в многих потоках, если вижу, что она const

Если учесть, что константные ф-ции нехорошо делать недетерминированными, то да, можешь.

Автор: Alek86 10.11.2007, 12:29
а mutable? он является чем-то плохим, что лучше не пользовать?

Автор: JackYF 10.11.2007, 13:45
Цитата(Alek86 @  10.11.2007,  12:29 Найти цитируемый пост)
он является чем-то плохим, что лучше не пользовать?

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

Автор: archimed7592 10.11.2007, 13:58
Цитата(Alek86 @  10.11.2007,  12:29 Найти цитируемый пост)
а mutable? он является чем-то плохим, что лучше не пользовать? 

Нет, с чего ты взял?

Автор: Alek86 10.11.2007, 16:16
Цитата(archimed7592 @  10.11.2007,  12:09 Найти цитируемый пост)
Если учесть, что константные ф-ции нехорошо делать недетерминированными, то да, можешь.


в смысле, если я вижу константную функцию, то я НАДЕЮСЬ, что она не меняет статическую mutable (по сути, глобальную переменную). А гарантий никаких.

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

Автор: MAKCim 10.11.2007, 16:39
Цитата(archimed7592 @  9.11.2007,  13:38 Найти цитируемый пост)
Кто-нибудь когда-нибудь встречал что-нибудь вроде этого?

не встречал
с трудом представляю, что оно может означать
у меня есть только один вариант
все поля в контексте volatile-метода являются volatile-полями, т. е их значения не кэшируются в регистрах при работе с ними
так?

Автор: archimed7592 10.11.2007, 16:42
Цитата(MAKCim @  10.11.2007,  16:39 Найти цитируемый пост)
все поля в контексте volatile-метода являются volatile-полями, т. е их значения не кэшируются в регистрах при работе с ними
так? 

Вестимо, что так... Ну и, по аналогии, из такого метода не вызвать другие, менее cv-квалифицированные методы.
Я вот только не приложу ума, как это можно использовать в реальной жизни smile.

Автор: MAKCim 10.11.2007, 16:51
Цитата(archimed7592 @  10.11.2007,  16:42 Найти цитируемый пост)
Я вот только не приложу ума, как это можно использовать в реальной жизни

по аналогии с volatile для переменных
метод вполне может вызываться извне (для одного и того же объекта)
извне = другой поток или какое-либо асинхронное событие в основном потоке

Автор: JackYF 11.11.2007, 00:38
MAKCim, итого - можно не ставить мутекс на чтение переменных, использующихся в методе. isn't it?

Автор: archimed7592 11.11.2007, 01:00
volatile переменные очень редкое явление и используются исключительно для работы с аппаратурой и для реализации самых примитивных примитивов синхронизации smile.

Добавлено через 3 минуты и 9 секунд
Цитата(JackYF @  11.11.2007,  00:38 Найти цитируемый пост)
MAKCim, итого - можно не ставить мутекс на чтение переменных, использующихся в методе. isn't it? 

Либо мьютексы можно было бы не ставить и без volatile, либо, volatile не поможет при работе без мьютексов smile. Короче говоря, понятия несопоставимые smile.

Автор: JackYF 11.11.2007, 02:51
archimed7592, ключевое слово в фразе было - "на чтение" smile

Автор: archimed7592 11.11.2007, 03:08
JackYF, ещё раз:
либо читать можно без мьютекса - т.е. есть гарантии, что во время чтения не будет произведена запись. Такая гарантия есть, либо, когда происходит атомарная операция чтения(к примеру, чтение long long на x86 не является атомарной операцией), либо когда нет других потоков, работающих с переменной на запись.
либо, если нужен мьютекс, volatile не поможет.

Т.е. в данном случае:
Цитата(MAKCim @  10.11.2007,  16:51 Найти цитируемый пост)
метод вполне может вызываться извне (для одного и того же объекта)
извне = другой поток или какое-либо асинхронное событие в основном потоке 

метод и так может быть вызван(без его volatile-квалификации), а остальное зависит от логики работы этого метода(см. выше).

volatile даёт только одну гарантию: компилятор не может переставлять местами обращение к volatile переменным(даже чтение).
К примеру есть два порта, mapped to address space и представленные volatile переменными. Допустим тебе нужно отправить в первый порт какую-нибудь управляющую команду, а потом прочитать из второго порта результат. Компилятор гарантирует, что он не всунет чтение из второго порта перед записью в первый. Если ты уберёшь volatile-квалификацию, то с точки зрения компилятора, запись в одну переменную и чтение из другой - совершенно независимые операции и вполне сможет переставить их местами, ибо observable behaviour из-за этого не изменится.

К слову, я не утверждаю "уберите нафик из стандарта возможность volatile-квалификации методов" smile. Я отлично понимаю, что сделано это из соображений общности(по крайней мере, чтобы убрать эту возможность придётся добавить в стандарт пару параграфоф, а никак не убрать), и если не использовать это, никому проблем оно не доставляет... Мне просто было интересно, может есть какое-нибудь не высосанное из пальца применение этой конструкции.

Автор: MAKCim 11.11.2007, 10:29
Цитата(archimed7592 @  11.11.2007,  03:08 Найти цитируемый пост)
чтение long long на x86 не является атомарной операцией

Код

extern long long foo;
...
long long value = 0;
__asm__("lock  cmpxchg8b (%6)" : "=a" (&value), "=d" ((char*)&value + 4) : "0" (0), "1" (0), "b" (0), "c"(0), "D" (&foo))

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

Автор: MAKCim 11.11.2007, 11:04
Цитата(archimed7592 @  11.11.2007,  03:08 Найти цитируемый пост)
Мне просто было интересно, может есть какое-нибудь не высосанное из пальца применение этой конструкции. 

ты же сам привел пример
вот реализация
Код

class io_apic {
private:
    unsigned int (*map)[1024];
    static const int IO_APIC_ADDRESS = 0;
    static const int IO_APIC_DATA = 0;
public:
    unsigned long long io_apic_read_rt(unsigned int number) volatile {
        map[IO_APIC_ADDRESS] = number << 1 + 16;
        return *static_cast<unsigned long long*>(&map[IO_APIC_DATA]);
    }
};

Автор: archimed7592 11.11.2007, 11:37
Цитата(MAKCim @  11.11.2007,  11:04 Найти цитируемый пост)
ты же сам привел пример

Ну этот пример немного из пальца ;). Присутствуют только volatile-квалифицированные данные и они просто не могут быть не volatile.
К примеру, если у меня в классе есть поле, которое по идее меняться не должно, я из "стилевых" соображений сделаю это поле const вне зависимости от квалификации метода. По аналогии: здесь тоже я бы сразу поставил volatile на массив. Хотя... Какой-то смысл я в volatile-квалификации мьютекса начинаю видеть smile.

Автор: JackYF 11.11.2007, 12:23
archimed7592, угу, да, понял.

Автор: MAKCim 11.11.2007, 12:39
Цитата(archimed7592 @  11.11.2007,  11:37 Найти цитируемый пост)
По аналогии: здесь тоже я бы сразу поставил volatile на массив. Хотя... Какой-то смысл я в volatile-квалификации мьютекса начинаю видеть

а зачем тут volatile на весь массив, если по сути volatile-поведение нужно только для одного метода?  smile 

Автор: archimed7592 11.11.2007, 16:20
Цитата(MAKCim @  11.11.2007,  12:39 Найти цитируемый пост)
а зачем тут volatile на весь массив, если по сути volatile-поведение нужно только для одного метода?  smile  

А для остальных не нужно? smile

Автор: MAKCim 11.11.2007, 16:31
Цитата(archimed7592 @  11.11.2007,  16:20 Найти цитируемый пост)
А для остальных не нужно?

нет
пример был не с потолка, а вполне реальный, для работы с I/O APIC
некоторые регистры отображены на физическое адресное пространство напрямую
а некоторые доступны косвенно через IO_APIC_DATA

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)