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

Различия компиляторов. В чем причина? - C++

Восстановить пароль Регистрация
 
Питекантроп
 Аватар для Питекантроп
246 / 140 / 6
Регистрация: 14.06.2010
Сообщений: 340
21.12.2011, 18:28     Различия компиляторов. В чем причина? #1
есть небольшой код, который успешно компилируется в VS 2010
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
#include <iostream>
 
template <class T>
class complex
{
public:
    T re, im;
    complex(T re = 0, T im = 0)
    {
        this->re = re;
        this->im = im;
    }
    complex(complex<T> & c)
    {
        this->re = c.re;
        this->im = c.im;
    }
 
    complex<T> operator + (complex<T> & c)
    {
        return complex<T>(re + c.re,im + c.im);
    }
 
    complex<T> operator - (complex<T> & c)
    {
        return complex<T>(re - c.re,im - c.im);
    }
    complex<T> & operator = (complex<T> & c)
    {
        this->re = c.re;
        this->im = c.im;
        return *this;
    }
    complex<T> operator + (T x)
    {
        return complex<T>(re + x,im);
    }
};
 
using namespace std;
int main(int argc, char* argv[])
{
    complex<double> a(1,3), b, c;
    c = a;
    b = a + c + 10;
    cout<<b.re<<" "<<b.im<<endl;
    cin.get();
    return 0;
}
При попытке переноса его на с++ builder 2010 возникают две ошибки:
1. Компилятору не нравится конструктор копирования. Интересно, что в старом добром builder 6 такой ошибки не возникает.
2. Не нравится вызов оператора = в строке
C++
1
b = a + c + 10;
Первое устраняется удалением конструктора копирования (он тут по сути и не нужен).
Второе - в передаче параметров оператора = через стек, а не по ссылке
C++
1
complex<T> & operator = (complex<T> c)
Просмотр дизассемблированного кода дает ожидаемые результаты: в VS передает в стек указетель, а билдер - копирует туда экземпляр класса (т.е. в случае double - в 4 раза больше).
Тестировал на компиляторе g++ - ему по душе билдеровский вариант.
Еще протестировал возврат результата по ссылке в случае с оператором +.
C++
1
2
3
4
    complex<T> & operator + (complex<T> & c)
    {
        return complex<T>(re + c.re,im + c.im);
    }
Билдер в этом случае не компилирует, а VS компилирует, но выдает неправильный результат (т.к. созданный локально стековый объект удаляется)

В чем же причина? Различные стандарты с++?
Или дело в неопределенном поведении, как, например, в таком случае?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
21.12.2011, 18:28     Различия компиляторов. В чем причина?
Посмотрите здесь:

Незнаю в чем причина C++
В чем причина ошибки? C++
В чем причина? C++
подскажите в чем причина.... C++
C++ Простейшая сортировка. В чем причина?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Kastaneda
Модератор
Эксперт С++
 Аватар для Kastaneda
4236 / 2769 / 218
Регистрация: 12.12.2009
Сообщений: 7,104
Записей в блоге: 1
Завершенные тесты: 1
21.12.2011, 19:31     Различия компиляторов. В чем причина? #2
C++
1
2
complex(const complex<T> & c){}
complex<T> & operator = (const complex<T> & c){}
конструктор копирования по стандарту принимает константный аргумент, поэтому билдер и g++ спотыкаются об это. Студия же выкручивается доступными средствами и, наверное, это не совсем по стадарту.
Как по стандарту выглядет operator=() я к сожалению не знаю (искать лень)), но с константым аргументом у меня компилируется.

Цитата Сообщение от Питекантроп Посмотреть сообщение
В чем же причина? Различные стандарты с++?
Или дело в неопределенном поведении, как, например, в таком случае?
Не думаю, что это UB, скорее особенности реализации. Давно известно, что компиляторы MS не шибко дружны со стандартом С/С++, но тем не менее они (MS) документируют подобные моменты, возможно об этом тоже написанно, да кто бы ее (документацию) читал
Питекантроп
 Аватар для Питекантроп
246 / 140 / 6
Регистрация: 14.06.2010
Сообщений: 340
22.12.2011, 00:52  [ТС]     Различия компиляторов. В чем причина? #3
таки да, const исправляет положение. И билдер и g++ компилируют.
Но в некоторых случаях компилируется и без const. Например, код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class X
{
public:
    int a;
    X() { a = 0; }
    X(X & x) { a = x.a; }
};
int main(int argc, char* argv[])
{
        X z;
        X z1(z);
                .......
}
компилируется без ошибок и предупреждений.
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
22.12.2011, 00:57     Различия компиляторов. В чем причина? #4
конструктор копирования с неконстантной ссылкой - это разрешено. вспоминаем стандартный auto_ptr, у которого конструктор копирования как раз с неконстантной ссылкой. в вашем же случае возможно ругань из-за того, что в вызывается конструктор копирования и ему передается неконстантная ссылка на временный объект. а вот это уже не очень то и разрешено. но студия умалчивает о таких ошибках.

C++
1
b = a + c + 10;
вот тут неявный каст из инта в complex<double> (т.е. создается временный объект) и он отдается оператору +, который почему-то с неконстантной ссылкой. потом еще раз зовется оператор + с предыдущей суммой, результат которой тоже во временном объекте. потом результат обеих сумм (который конечно же во временном объекте) передается в оператор =, который точно так же с неконстантной ссылкой.

все, что метод не изменяет должно передаваться по константной ссылке или же по значению. иначе интерфейс вызывает недоверие и в некоторых случаях не компилится. Эта болезнь у всех ваших операторов в исходном классе.
Питекантроп
 Аватар для Питекантроп
246 / 140 / 6
Регистрация: 14.06.2010
Сообщений: 340
22.12.2011, 04:01  [ТС]     Различия компиляторов. В чем причина? #5
Цитата Сообщение от DU Посмотреть сообщение
вызывается конструктор копирования и ему передается неконстантная ссылка на временный объект. а вот это уже не очень то и разрешено.
Таки да. Если передавать невременные объекты, то все работает.

Цитата Сообщение от DU Посмотреть сообщение
вот тут неявный каст из инта в complex<double>
такой каст вряд ли бы произошел неявно =)). Тут каст из инт в дабл и вызов
C++
1
complex<double> operator + (double x) {}
Впрочем, это сути не меняет. Спасибо за ответ.
Yandex
Объявления
22.12.2011, 04:01     Различия компиляторов. В чем причина?
Ответ Создать тему
Опции темы

Текущее время: 01:50. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru