Возможно малочисленному сообществу разработчиков для WinCE
будет интересно знать о следующей проблеме, с которой я только что столкнулся.
class CTestClass
{
public:
CTestClass()
{
wchar_t mess[100];
swprintf(mess,_T("this == %p"),this);
::MessageBox(NULL,mess,_T("default constructor"),0);
}
CTestClass(const CTestClass& other)
{
wchar_t mess[100];
swprintf(mess,_T("this == %p, &other == %p"),this,&other);
::MessageBox(NULL,mess,_T("copy constructor"),0);
}
virtual ~CTestClass()
{
wchar_t mess[100];
swprintf(mess,_T("this == %p"),this);
::MessageBox(NULL,mess,_T("destructor"),0);
}
};
void TestAction(CTestClass obj)
{
wchar_t mess[100];
swprintf(mess,_T("&obj == %p"),&obj);
::MessageBox(NULL,mess,_T("TestAction"),0);
}
Если вызвать функцию TestAction следующим образом,
TestAction(CTestClass());
то программа покажет 3 разных диалога:
— диалог от "default constructor"
— диалог от функции "TestAction"
— диалог от "destructor".
Так вот, адреса, которые будут показаны в 1-м случае и
в двух других случаях, будут разными

.
Еще осталось добавить, что все это справедливо для eVC 4.0
с установленным сервис паком. Генерация кода проводилась для
процессора "ARMV4I". Компилятор для эмулятора этой проблемы не имеет.
Компиляторы для других процессоров проверить, к сожалению, не могу.
12.09.03 18:44: Перенесено модератором из 'C/C++' — AS
Здравствуйте, bkat, Вы писали:
B>Возможно малочисленному сообществу разработчиков для WinCE
B>будет интересно знать о следующей проблеме, с которой я только что столкнулся.
B>Если вызвать функцию TestAction следующим образом,
B>B>TestAction(CTestClass());
B>
B>то программа покажет 3 разных диалога:
B>- диалог от "default constructor"
B>- диалог от функции "TestAction"
B>- диалог от "destructor".
B>Так вот, адреса, которые будут показаны в 1-м случае и
B>в двух других случаях, будут разными
.
сдесь все нормально:
поинтер на класс перемещается, потому разные адреса.
показывает адрес однои функции, другои... и тд.
Здравствуйте, IvanGrozny, Вы писали:
IG>Здравствуйте, bkat, Вы писали:
B>Возможно малочисленному сообществу разработчиков для WinCE
B>будет интересно знать о следующей проблеме, с которой я только что столкнулся.
B>Если вызвать функцию TestAction следующим образом,
B>B>TestAction(CTestClass());
B>
B>то программа покажет 3 разных диалога:
B>- диалог от "default constructor"
B>- диалог от функции "TestAction"
B>- диалог от "destructor".
B>Так вот, адреса, которые будут показаны в 1-м случае и
B>в двух других случаях, будут разными
.
IG>сдесь все нормально:
IG>поинтер на класс перемещается, потому разные адреса.
IG>показывает адрес однои функции, другои... и тд.
Что-то не понял... Куда и зачем перемещается поинтер на класс?
Можно немного подробней?
Кстати, а что ты ожидаешь увидеть, если выполнить?
CTestClass originalObj;
TestAction(originalObj);
В этом случае, кстати, copy constructor и функция TestAction
тоже покажут разные адреса.
Ну и, наконец, что если CTestClass будет таким:
class CTestClass
{
CTestClass *m_this;
public:
CTestClass()
{
m_this = this;
}
CTestClass(const CTestClass& other)
{
m_this = this;
}
virtual ~CTestClass()
{
assert(m_this==this);
}
};
В моем случае мы напоремся на assert в деструкторе.
Здравствуйте, bkat, Вы писали:
B>Так вот, адреса, которые будут показаны в 1-м случае и
B>в двух других случаях, будут разными
.
IG>сдесь все нормально:
IG>поинтер на класс перемещается, потому разные адреса.
IG>показывает адрес однои функции, другои... и тд.
B>Что-то не понял... Куда и зачем перемещается поинтер на класс?
B>Можно немного подробней?
в одном случае ты береш адрес, на которыи указывает Handle обекта при вызове функции constructora,
в другом референцию на класс.. а в деструкторе адрес ,указываемыи Handlom перед уничтожением.
B>Кстати, а что ты ожидаешь увидеть, если выполнить?
B>B>CTestClass originalObj;
B>TestAction(originalObj);
B>
ну, предполагаю, что адреса так же будут разными..
B>В этом случае, кстати, copy constructor и функция TestAction
B>тоже покажут разные адреса.
B>Ну и, наконец, что если CTestClass будет таким:
B>B>class CTestClass
B>{
B> CTestClass *m_this;
B>public:
B> CTestClass()
B> {
B> m_this = this;
B> }
B> CTestClass(const CTestClass& other)
B> {
B> m_this = this;
B> }
B> virtual ~CTestClass()
B> {
B> assert(m_this==this);
B> }
B>};
B>
B>В моем случае мы напоремся на assert в деструкторе.
и сдесь все то же самое.
извини, если что..
Здравствуйте, IvanGrozny, Вы писали:
B>Ну и, наконец, что если CTestClass будет таким:
B>B>class CTestClass
B>{
B> CTestClass *m_this;
B>public:
B> CTestClass()
B> {
B> m_this = this;
B> }
B> CTestClass(const CTestClass& other)
B> {
B> m_this = this;
B> }
B> virtual ~CTestClass()
B> {
B> assert(m_this==this);
B> }
B>};
B>
B>В моем случае мы напоремся на assert в деструкторе.
IG>и сдесь все то же самое.
IG> извини, если что..
Я бы сказал это довольно странно, что у объекта
во время его жизни меняется значение this.
Здравствуйте, bkat, Вы писали:
B>B>void TestAction(CTestClass obj)
B>
B>то программа покажет 3 разных диалога:
B>- диалог от "default constructor"
B>- диалог от функции "TestAction"
B>- диалог от "destructor".
Ф-ция принимает аргумент по значению. Происходит copy initialization формального аргумента, как
CTestClass obj = CTestClass();
Компилятор может произвести трансформацию кода (именно трансформацию, не оптимизацию), чтобы заменить copy initialization на direct initialization. Это позволено даже в том случае, когда конструктор имеет побочный эффект. Что, по-видимому, мы и наблюдаем.
Здравствуйте, MaximE, Вы писали:
ME>Здравствуйте, bkat, Вы писали:
B>B>void TestAction(CTestClass obj)
B>
B>то программа покажет 3 разных диалога:
B>- диалог от "default constructor"
B>- диалог от функции "TestAction"
B>- диалог от "destructor".
ME>Ф-ция принимает аргумент по значению. Происходит copy initialization формального аргумента, как
ME>ME>CTestClass obj = CTestClass();
ME>
ME>Компилятор может произвести трансформацию кода (именно трансформацию, не оптимизацию), чтобы заменить copy initialization на direct initialization. Это позволено даже в том случае, когда конструктор имеет побочный эффект. Что, по-видимому, мы и наблюдаем.
Проблема, как я понял, заключается в том, что указатели 'this' различаются в конструкторе и деструкторе. Это означает одно из двух:
— мы имеем дело с двумя разными объектами, один из которых не конструируется вызовом конструкора, а другой — не деструктируется вызовом деструктора
— мы имеем дело с "одним" объектом (результат описываемой тобой трансформации), но вследствие какого-то глюка компилятора значения 'this' в деструкторе оказывается неверным
В любом случае (а имеет место, скорее всего, именно первый вариант) данное поведение компилятора является багом.