конструктор копирования не вызывается

Тема в разделе "LANGS.C", создана пользователем systemio, 9 дек 2010.

  1. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    Добрый вечер всем.
    Только что узнал что конструктор копирования и деструктор не вызывается если функция возвращает объект создавая, но если сначала создать объект, а потом возвратить, то поведение ожидаемое. Кто знает что это: стандарт или оптимизация некая VS2003(7.1)?

    struct sS
    {
    int i;
    sS(int ii):
    i(ii)
    {
    }
    sS(const sS& s):
    i(s.i)
    {
    }
    const sS& operator =(const sS& s)
    {
    i = s.i;
    return *this;
    }
    ~sS()
    {
    i = 0;
    }
    };

    sS FS(int i)
    {
    //sS s(i); return s;
    return sS(i);
    }

    int main(int argc, char* argv[])
    {
    {
    sS s1 = FS(5);
    sS& s2 = FS(15);
    sS& s3 = FS(25);
    bool b = (s1.i == s2.i == s3.i);
    }
    } // Выход
     
  2. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    systemio
    Это называется RVO (return value optimization). Разрешено Стандартом.
    Применяется всеми продвинутыми компиляторами.
     
  3. Booster

    Booster New Member

    Публикаций:
    0
    Регистрация:
    26 ноя 2004
    Сообщения:
    4.860
    Откуда RVO у VS2003?
     
  4. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    я ставил брэйкпоинты - через принтф мне не нравится.

    green
    спасибо за подсказку - впервые слышу об этом. вот нашел в вики
    http://en.wikipedia.org/wiki/Return_value_optimization
     
  5. green

    green New Member

    Публикаций:
    0
    Регистрация:
    15 июл 2003
    Сообщения:
    1.217
    Адрес:
    Ukraine
    Вызывается, но только целевой. При RVO опускается создание/удаление промежуточных объектов (и, следовательно, вызов копирующего конструктора/деструктора).
    Booster
    Частично RVO умеет даже VS6.

    В данном примере, насколько я понимаю, RVO должна была сработать в обоих случаях. Видимо, RVO в VS2003 реализована недостаточно хорошо.
     
  6. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    это ахтунг (неконстантная ссылка на временный объект
    неопределенное поведение)
    если бы объект был не просто целая переменная
    а указатель в кучу то он был бы уже невалидный
    при сравнении

    и еще в си++ в отличии от си операция присваивания
    имеет lvalue результат
    const sS& operator =(const sS& s)
    это не соответствует семантике встроенных типов
    надо так
    sS& operator =(const sS& s)

    примерно так
    int a;
    (((a = 1) = 2) = 3);
    mov dword ptr [a],1
    lea eax,[a]
    mov dword ptr [ebp-74h],eax
    mov ecx,dword ptr [ebp-74h]
    mov dword ptr [ecx],2
    mov edx,dword ptr [ebp-74h]
    mov dword ptr [edx],3

    class int{
    int& operator=(const int &r){
    this->int_internal_present = r.int_internal_present;
    return *this;
    }
    }
     
  7. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    osox
    согласен про оператор =
    насчет ссылок - просто удивило что это компилится и работает.