Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

С++, список инициализатора

602
17 сентября 2009 года
KPI Student
265 / / 16.12.2006
Подсткажите, пожалуйста, то ли я чего-то не понимаю, то ли GCC 4.3 под 64-битную Debian работает неправильно... Неправильно - это конечно слишком громко, но не соответствует стандарту.

Суть проблемы, есть такой код:

 
Код:
CPipedFactorialCalculator::CPipedFactorialCalculator(unsigned int x, const CBaseLog& logger)
: m_pipe        ()
, m_initialValue(x)
, m_logger      ( logger.createCopy() )
, m_pid         ( ::fork() )
{
   ...
}



Зачем считать факториал в отдельном потоке - потому, что того требует задание на лабу. То же и с пайпами.

Я думаю, вызов конструктора должен выполнятся следующим образом:
1. создается объект m_pipe,
2. создается объект m_initialValue
3. создается объект m_logger
4. создается объект m_pid - в этот момент происходит "раздвоение на два процесса"
5. создаются остальные члены класса, не указанные в списке инициализатора.

На самом же деле сначала "раздваивается на два процесса", и лишь затем обрабатывается список инициализатора.

Решение-то конечно простейшее, fork вынести в тело конструктора, но все же не приятно... Скажите, пожалуйста, кто ошибается, я или компилятор? :)
260
17 сентября 2009 года
Ramon
1.1K / / 16.08.2003
Объявление класса в студию.
602
17 сентября 2009 года
KPI Student
265 / / 16.12.2006
Код:
class CBaseLog;


class CPipedFactorialCalculator          // управляет взаимодействием процессов
{
    typedef auto_ptr<CBaseLog> TLoggerPtr;

public:
    CPipedFactorialCalculator (unsigned int x, const CBaseLog& logger);
    ~CPipedFactorialCalculator();

    double getResult();
    bool   setResult(double result);

private:
    pid_t        m_pid;
    CPipe        m_pipe;
    unsigned int m_initialValue;
    TLoggerPtr   m_logger;


    bool         isChild          ()    {return m_pid == 0;}
    bool         isValid          ()    {return m_pid !=-1;}
    bool         calculate        ();
};
260
17 сентября 2009 года
Ramon
1.1K / / 16.08.2003
Где объявлен m_pid? Правильно, раньше всего остального, а компилятор зовет инициализаторы в порядке именно объявления и обычно варнингом предупреждает, что вы написали в конструкторе инициализаторы не в том порядке как объявлены относящиеся к ним объекты.

PS: Таков стандарт.
602
17 сентября 2009 года
KPI Student
265 / / 16.12.2006
Да, действительно, вызов происходит в том порядке, в котором члены объявлены в классе. Спасибо, буду знать!

ЗЫ. По умолчанию этот варнинг отключен...
602
17 сентября 2009 года
KPI Student
265 / / 16.12.2006
Да, все-таки -Wall рулит))) А сколько времени было потрачено...

С этой опцией действительно выдает следующее:
 
Код:
child.h: In constructor ‘CPipedFactorialCalculator::CPipedFactorialCalculator(unsigned int, const CBaseLog&)’:
child.h:29: предупреждение: ‘CPipedFactorialCalculator::m_pipe’ будет инициализирован после
child.h:28: предупреждение:   ‘pid_t CPipedFactorialCalculator::m_pid’
child.cpp:14: предупреждение:   when initialized here
52K
13 октября 2009 года
Serebrjany mir
10 / / 11.09.2009
Значения функций, возвращаемых в список инициализации, вычисляются до начала инициализации элементов т.е. вызов m_pidfork расладывается на pid_t __temp_pid = fork; m_pid__temp_pid;. Чтобы все работало так как вы хотите, надо использовать язык подерживающий lazy evaluations.
3
14 октября 2009 года
Green
4.8K / / 20.01.2000
Цитата: Serebrjany mir

Значения функций, возвращаемых в список инициализации, вычисляются до начала инициализации элементов


Покажи пункт стандарта это регламентирующий.
Практика показывает иное:

Код:
#include <iostream>
using namespace std;

struct A
{
    A(int val)
    {
        cout << "A(int)" << endl;
    }
};

int func()
{
    cout << "func()" << endl;
    return 1;
}

struct B
{
    A a1, a2;

    B() :a1(func()), a2(func())
    {
        cout << "B()" << endl;
    }
};

int main()
{
    B b;
    return 0;
}

Вывод:
Цитата:

func()
A(int)
func()
A(int)
B()


Цитата: Serebrjany mir

Чтобы все работало так как вы хотите, надо использовать язык подерживающий lazy evaluations.


Зачем?
Кстати, отложенные вычисления эмулируются и C++.

260
14 октября 2009 года
Ramon
1.1K / / 16.08.2003
Цитата: Serebrjany mir
Значения функций, возвращаемых в список инициализации, вычисляются до начала инициализации элементов т.е. вызов m_pidfork расладывается на pid_t __temp_pid = fork; m_pid__temp_pid;. Чтобы все работало так как вы хотите, надо использовать язык подерживающий lazy evaluations.



ISO/IEC 14882

Цитата:

12.6.2 Initializing bases and members

...
There is a sequence point (1.9) after the initialization of each base and member. The expression-list of a mem-initializer is evaluated as part of the initialization of the corresponding base or member.
...

14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Поцаны. Вам не кажется что это - бот?!
3
14 октября 2009 года
Green
4.8K / / 20.01.2000
Цитата: Phodopus
Поцаны. Вам не кажется что это - бот?!


Точняк...
Забанен!

14
14 октября 2009 года
Phodopus
3.3K / / 19.06.2008
Ппц.. Я с самого момента его появления раза 3 жаловался точно. А это уже давно было! А вы с ним разговоры затеваете :D
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог