operator float () ... вопрос
От: tealex  
Дата: 05.02.08 13:14
Оценка:
О всевышний ! Ответь мне на вопрос !
class Counter 
{
public:
    int count ;

    Counter (int a ): count (a){}

    Counter (Counter &x)
    {
        count = x.count ;
    }

    Counter operator ++()
    {
        Counter a(1);
        return a;//Counter (1);  
    }

    operator float ()const
    {
        return 25.0F;
    }
};


такой класс нормально компиллится (VS 8)

class Counter 
{
public:
    int count ;

    Counter (int a ): count (a){}

    Counter (Counter &x)
    {
        count = x.count ;
    }

    Counter operator ++()
    { 
             return Counter (1);   //WARNING : warning C4244: 'argument' : conversion from 'float' to 'int', possible loss of data
    }

    operator float ()const
    {
        return 25.0F;
    }
};


a вот этот при компиляции выдаётся варнинг

Это как-то связанно с operator float ()const и конструктором копирования : но не пойму как
хана
Re: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 13:20
Оценка:
Здравствуйте, tealex, Вы писали:

T>О всевышний ! Ответь мне на вопрос !


T> Counter (Counter const& x)




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 13:42
Оценка: 28 (1)
Здравствуйте, remark, Вы писали:

R>Здравствуйте, tealex, Вы писали:


T>>О всевышний ! Ответь мне на вопрос !


T>> Counter (Counter const& x)


Посколько конструктор копирования принимает только неконстантную ссылку, то компилятор не может скопировать временную переменную, созданную в operator++() в возвращаемое значение. Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.
Подозреваю, что такая последовательность преобразований является расширением msvc и не соотв. стандарту, т.к. содержит 2 пользовательских преобразования.
Если быть более точным, то msvc может связать временный объект и неконстантную ссылку. Просто видимо она считает это преобразование менее приоритетным. Сказать тут что-либо сложно, т.к. оба преобразования — расширения msvc. А эти расширения являются большей частью недокументированными.
Если это всё подытожить, то надо передавать копию в конструктор копирования как константную ссылку.

R>


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 13:47
Оценка:
Здравствуйте, remark, Вы писали:

T>> Counter (Counter const& x)


Ok )

действительно не ругается но причём здесь operator float () ??????? вообще этот const по сути и не обязателен ;

и ещё
в чём разница между

Counter const& x

const Counter & x
хана
Re[3]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 13:53
Оценка: +1
Здравствуйте, tealex, Вы писали:

T>Здравствуйте, remark, Вы писали:


T>>> Counter (Counter const& x)


T>Ok )


T>действительно не ругается но причём здесь operator float () ???????


http://gzip.rsdn.ru/forum/message/2825441.1.aspx
Автор: remark
Дата: 05.02.08


T>вообще этот const по сути и не обязателен ;


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


T>и ещё

T>в чём разница между

T>
T>Counter const& x

T>const Counter & x
T>



Первое — ссылка на константный счётчик
Второе — ссылка на счётчик константный
Короче — ни в чём


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 13:55
Оценка:
R> Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.

Это что дизасемблер ?


хана
Re[3]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 14:00
Оценка:
T>>> Counter (Counter const& x)

R>Посколько конструктор копирования принимает только неконстантную ссылку, то компилятор не может скопировать временную переменную, созданную в operator++() в возвращаемое значение. Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.

R>Подозреваю, что такая последовательность преобразований является расширением msvc и не соотв. стандарту, т.к. содержит 2 пользовательских преобразования.
R>Если быть более точным, то msvc может связать временный объект и неконстантную ссылку. Просто видимо она считает это преобразование менее приоритетным. Сказать тут что-либо сложно, т.к. оба преобразования — расширения msvc. А эти расширения являются большей частью недокументированными.
R>Если это всё подытожить, то надо передавать копию в конструктор копирования как константную ссылку.

А на это же не ругается , хотя в принципе там то же вызывается копирующий конструктор
Counter a(1);
return a;

в отличии от этого
return Counter (1);




хана
Re[4]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 14:03
Оценка:
Здравствуйте, tealex, Вы писали:


R>> Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.


T>Это что дизасемблер ?



Да нет, просто отладчик студии с применением функции Step In (F11)
Ну или можно было отладочного вывода во все функции понапихать...


T>


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 14:08
Оценка: +1
Здравствуйте, tealex, Вы писали:


T>>>> Counter (Counter const& x)


R>>Посколько конструктор копирования принимает только неконстантную ссылку, то компилятор не может скопировать временную переменную, созданную в operator++() в возвращаемое значение. Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.

R>>Подозреваю, что такая последовательность преобразований является расширением msvc и не соотв. стандарту, т.к. содержит 2 пользовательских преобразования.
R>>Если быть более точным, то msvc может связать временный объект и неконстантную ссылку. Просто видимо она считает это преобразование менее приоритетным. Сказать тут что-либо сложно, т.к. оба преобразования — расширения msvc. А эти расширения являются большей частью недокументированными.
R>>Если это всё подытожить, то надо передавать копию в конструктор копирования как константную ссылку.

T>А на это же не ругается , хотя в принципе там то же вызывается копирующий конструктор

T>
T>Counter a(1);
T>return a;
T>

T>в отличии от этого
T>
T>return Counter (1);  
T>



Тут не временный объект (r-value), а обычный объект (l-value). Неконстантные l-value без проблем связываются с неконстантными ссылками. r-value и константные и неконстантные *не* связываются с неконстантными ссылками. (хотя студия это умеет делать, но это уже отдельный вопрос)
Т.ч. разница есть. И, объявив конструктор копирования как Counter (Counter& x), ты как раз сказал коспилятору, что *хочешь* различать эту разницу. Если ты объявляешь как Counter (Counter const& x), то ты говоришь, что *не* хочешь различать эту разницу.


T>


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 14:09
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, tealex, Вы писали:



R>>> Поэтому msvc производит достаточно странную последовательность действий. Она вызывает у временного объекта operator float(), потом преобразует float в int, потом конструирует возвращаемое значение с помощью этого int'а.


T>>Это что дизасемблер ?



R>Да нет, просто отладчик студии с применением функции Step In (F11)

R>Ну или можно было отладочного вывода во все функции понапихать...

ясно ))

T>>

R>
хана
Re[5]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 14:32
Оценка:
Я понял .
Если я передаю временный обьект(по сылке) то функция принимающая должна принимать const (иначе не произойдёт связование)
Если не временный обьект то функция принимающая может быть как const так и не const

типа того ) ?

ну на саом деле ситуция не тривиальная )

если бы не operator float то я бы просто пропустил

хана
Re[6]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 14:40
Оценка:
Здравствуйте, tealex, Вы писали:

T>Я понял .

T>Если я передаю временный обьект(по сылке) то функция принимающая должна принимать const (иначе не произойдёт связование)
T>Если не временный обьект то функция принимающая может быть как const так и не const

T>типа того ) ?


Именно.
Либо можно принимать по значению, если объект "лёгкий".


T>


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[7]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 14:55
Оценка:
Ну ещё вопросы:

почему в этом случае вызывается конструктор копирования

   Counter a(77);
   return a;

а в этом нет
return Counter (77);

опять не тривиально для меня )))


class Counter 
{
public:
    int count ;

    Counter (int a ): count (a){}

    Counter (const Counter & x)
    {
        count = x.count ;
        printf ("constructor");
    }

    Counter operator ++()
    {
           Counter a(77);
           return a;   
        //return Counter (7);
    }

    operator float ()const
    {
        return 25.0F;
    }
};

int main(int argc, char* argv[])
{

    Counter a(111);
    Counter b(100);
    
    printf ("\n a = %d \n",a.count);
    printf ("\n b = %d \n",b.count);

    b = ++a;

    printf ("\n a = %d \n",a.count);
    printf ("\n b = %d \n",b.count)

вывод

a = 111

b = 100
constructor
a = 111

b = 77



class Counter 
{
public:
    int count ;

    Counter (int a ): count (a){}

    Counter (const Counter & x)
    {
        count = x.count ;
        printf ("constructor");
    }

    Counter operator ++()
    {
           //Counter a(77);
           //return a;   
        return Counter (7);
    }

    operator float ()const
    {
        return 25.0F;
    }
};

int main(int argc, char* argv[])
{

    Counter a(111);
    Counter b(100);
    
    printf ("\n a = %d \n",a.count);
    printf ("\n b = %d \n",b.count);

    b = ++a;

    printf ("\n a = %d \n",a.count);
    printf ("\n b = %d \n",b.count);



a = 111

b = 100

a = 111

b = 7
хана
Re[8]: operator float () ... вопрос
От: remark Россия http://www.1024cores.net/
Дата: 05.02.08 15:03
Оценка:
Здравствуйте, tealex, Вы писали:

T>Ну ещё вопросы:


T>почему в этом случае вызывается конструктор копирования


T>
T>   Counter a(77);
T>   return a;  
T>

T>а в этом нет
T>
T>return Counter (77);
T>

T> опять не тривиально для меня )))


Это implementation defined поведение. Конструктор копирования может вызываться и во втором случае.
Т.е. просто студия посчитала, что во втором случае элиминировать копирование легче и сделала это.



1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: operator float () ... вопрос
От: tealex  
Дата: 05.02.08 15:10
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, tealex, Вы писали:


T>>Ну ещё вопросы:


T>>почему в этом случае вызывается конструктор копирования


T>>
T>>   Counter a(77);
T>>   return a;  
T>>

T>>а в этом нет
T>>
T>>return Counter (77);
T>>

T>> опять не тривиально для меня )))


R>Это implementation defined поведение. Конструктор копирования может вызываться и во втором случае.

R>Т.е. просто студия посчитала, что во втором случае элиминировать копирование легче и сделала это.

ok )


хана
Re[4]: operator float () ... вопрос
От: AlexCrush Россия  
Дата: 05.02.08 15:15
Оценка:
Здравствуйте, remark, Вы писали:

R>Первое — ссылка на константный счётчик

R>Второе — ссылка на счётчик константный
R>Короче — ни в чём

Дополню, что есть полезное правило — const действует на то, что написано слева от него. Если слева ничего нет, то const действует на то что справа
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.