2013-08-12 4 views
1

Я ищу C++ 11 Перемещение конструкторов, но что-то не работает. На самом деле проблема еще до того, как я начал писать такой конструктор. Вот код отрезала:Не ожидается конструктор под названием

#include <iostream> 
#include <string> 
#include <sstream> 

class Object { 
    static std::ostream& log(Object &obj) { 
     std::cout << "Object::id = " << obj.mId << "::"; 
     return std::cout; 
    } 

    unsigned mId = 0; 
    std::string *mText = nullptr; 

    unsigned nextUniqueId() const { 
     static unsigned id = 0; 
     return ++id; 
    } 

    const std::string textInfo() const { 
     std::ostringstream oss; 
     oss << "mText @ " << &mText; 
     if (mText) oss << " = " << *mText; 

     return oss.str(); 
    } 

public: 
    Object() = delete; 
    Object& operator= (const Object&) = delete; 

    explicit Object(const std::string& str) : mId(this->nextUniqueId()), mText(new std::string(str)) { 
     Object::log(*this) << "constructor::one-argument\n"; 
    } 

    Object(const Object& obj) : mId(this->nextUniqueId()), mText(new std::string(*obj.mText)) { 
     Object::log(*this) << "constructor::copy\n"; 
    } 

    virtual ~Object() { 
     Object::log(*this) << "destructor::" << this->textInfo() << "\n"; 
     if (mText) { 
      delete mText; 
      mText = nullptr; 
     } 
    } 
}; 

static Object get_object() { 
    return Object("random text"); 
} 

int main(int argc, char **argv) { 
    Object a("first object"); // OK 

    /* 
    * Expected behaviour: inside get_object() function new Object is created which is then copied into 
    * variable b. So that new ID should be given. 
    */ 
    Object b = get_object(); // What the hell?! Not what expected! Why? 

    std::cout << std::endl; 
    return 0; 
} 

Ожидаемый выход похож на это:

Object::id = 1::constructor::one-argument  
Object::id = 2::constructor::one-argument 
Object::id = 2::destructor::mText @ 0x7fff32c25f70 = random text 
Object::id = 3::constructor::copy 

Object::id = 3::destructor::mText @ <DIFFERENT THAN IN ID=2> = random text 
Object::id = 1::destructor::mText @ 0x7fff32c25f90 = first object 

я получаю вместо этого:

Object::id = 1::constructor::one-argument 
Object::id = 2::constructor::one-argument 

Object::id = 2::destructor::mText @ 0x7fff32c25f70 = random text 
Object::id = 1::destructor::mText @ 0x7fff32c25f90 = first object 

который выглядит как переменная b создается на месте (что-то например inline?). Честно говоря, я не знаю, что происходит, может ли кто-нибудь объяснить?

+2

Это называется [оптимизация возвращаемого значения] (https://en.wikipedia.org/wiki/Return_value_optimization). Если вы используете gcc try для компиляции с помощью переключателя '-fno-elide-constructors', чтобы исключить возможность копирования. – Praetorian

+0

Хорошо, и это RVO работает всегда? Независимо от сложности (в коде) функции '' get_object() ''? – Robin92

+0

Нет, нет никакой гарантии, что это всегда произойдет, но это очень распространенная техника оптимизации, и, вероятно, будет сложно предотвратить компилятор от этого не делать по умолчанию. Кроме того, как упоминалось на странице Википедии *, реализация может опустить операцию копирования, вызванную оператором return, даже если конструктор копирования имеет побочные эффекты *. Таким образом, код внутри конструктора копирования не имеет значения. Что касается функции 'get_object()', если у вас несколько операторов return, и, возможно, они не все возвращают один и тот же тип (но типы конвертируются в 'Object'), вы можете предотвратить RVO, но это сомнительно – Praetorian

ответ

1

Компилятор разрешается применять «оптимизацию возвращаемого значения» РВО, и поэтому копия оптимизированные. Обратите внимание, что стандарт позволяет это, несмотря на побочные эффекты, связанные с выходным сообщением

3

Компилятор оптимизированный копировальный/переместить все ...

3

Это называется оптимизацией возвращаемого значения или RVO. Компилятор решил создать временный номер, возвращенный get_object() непосредственно в ячейке памяти b в main. Он санкционирован стандартом и очень распространенной оптимизацией.

Смежные вопросы