static_cast и временное создание (окончательная редакция)

Предпосылки: Чтобы понять этот вопрос, сначала прочитайте следующий вопрос и ответ на него: Привести auto_ptr‹Base› к auto_ptr‹Derived›

В Приведение auto_ptr‹Base› к auto_ptr‹Derived› Стив ответил, что "Ваш static_cast скопирует auto_ptr во временный файл, поэтому aS будет сброшен, а ресурс будет уничтожен, когда временный будет (в конце оператора)".

Меня интересует процесс временного создания при вызове static_cast. Я хотел бы иметь код, который я могу отследить, чтобы увидеть этот эффект. Я не могу использовать static_cast<auto_ptr<Circle>> ..., потому что он не может быть скомпилирован, поэтому мне нужно написать какой-то класс моделирования вместо auto_ptr и наблюдать за процессом временного создания.

Я также понимаю, что временное создание тесно связано с вызовом конструктора копирования. Потеря права собственности auto_ptr моделируется с помощью назначения копии, которое устанавливает для поля _radius источника отрицательное значение (мне нужна простая логическая модель auto_ptr).

Итак, я предлагаю следующий класс Circle:

#include <iostream>

class Shape {};

class Circle: public Shape {
  double _radius;
public:
  explicit Circle(double radius = .5): _radius(radius) {}
  Circle &operator =(Circle &circle) {
    _radius = circle._radius;
    circle._radius = -1.;
    return *this;
  }
  Circle(Circle &circle) { *this = circle; }
  double GetRadius() { return _radius; }
};

int wmain() {
  using namespace std;

  Circle c1(100), c2(200), c3(300);
  c2 = c3;

  Shape *s1, s2;
  s1 = &c1;
  wcout << static_cast<Circle *>(s1)->GetRadius() << endl;

  return 0;
}

В порядке. Здесь мы видим, что «передача права собственности» происходит в c2 = c3. НО не могу добиться временного создания в static_cast.

Вопрос: как сделать небольшую симуляцию создания временного объекта во время static_cast?

Я считаю, Стив, что временный объект создается во время кастинга. Единственное, что я хочу, это написать пример, показывающий временное создание. Эта цель имеет академические причины.

Может ли кто-нибудь прояснить, как добиться эффекта, описанного в ответе Стива, который он опубликовал в упомянутой теме?


person nickolay    schedule 20.12.2011    source источник
comment
Ваше описание ссылается на auto_ptr..., который вообще не используется в вашем примере кода. Не могли бы вы уточнить?   -  person Cameron    schedule 21.12.2011
comment
int wmain() не является стандартной основной функцией С++.   -  person BЈовић    schedule 21.12.2011
comment
@wilhelmtell Я отредактировал вопрос. Пожалуйста, перечитайте, если вам это интересно.   -  person nickolay    schedule 21.12.2011
comment
Для этого должен быть вызван оператор). какой оператор?   -  person curiousguy    schedule 21.12.2011
comment
@curiousguy - исправлено!   -  person nickolay    schedule 21.12.2011
comment
s1 = static_cast<Shape *>(&c2) почему бы не просто s1 = &c2;?   -  person curiousguy    schedule 21.12.2011
comment
Итак, ваш вопрос действительно таков: когда operator= вызывается неявно?   -  person curiousguy    schedule 21.12.2011
comment
@curiousguy Нет. :) Я вижу, мне нужно переформулировать первоначальный вопрос. Одну минуту.   -  person nickolay    schedule 21.12.2011


Ответы (4)


В вашем предыдущем вопросе auto_ptr - это класс, который имеет право собственности и сбрасывает указатель источника на нуль при его копировании.

Теперь Circle — это класс, который имитирует владение, сбрасывая его радиус до -1 при копировании. Так что это похоже на auto_ptr в этом смысле, но никак иначе.

Таким образом, чтобы наблюдать потерю симулированного права собственности, вам нужно скопировать Circle, что вы и делаете с назначением копирования в строке c2 = c3. Приведение Circle* не копирует объект, а только указатель, но приведение Circle копирует объект:

int main() {
    Circle c1(100);
    static_cast<Circle>(c1);
    std::cout << c1.GetRadius() << '\n';
}

Выход равен -1.

Или, если вы специально хотите увидеть его с приведением к производному классу:

struct SpecialCircle: Circle {
    SpecialCircle(Circle &circle) : Circle(circle) {}
    explicit SpecialCircle(double radius = .5): Circle(radius) {}
};

int main() {
    SpecialCircle s1(100);
    Circle &c1 = s1;
    static_cast<SpecialCircle>(c1);
    std::cout << c1.GetRadius() << '\n';
}
person Steve Jessop    schedule 21.12.2011
comment
ДААААААААААААААААААААААААА! Спасибо. Стив, я с нетерпением жду возможности обратиться к вам за помощью в моих последующих выпусках. Спасибо всем, ребята. Вот что мне нужно услышать. - person nickolay; 21.12.2011
comment
@папаМ:. Проблема с вашим кодом заключалась в том, что вы создавали временный указатель, а не временный цикл. - person Mooing Duck; 21.12.2011
comment
@MooingDuck Ага. Я понял этот факт и получил стек с тем, как реализовать приведение без указателя для вызова перегруженных операторов. - person nickolay; 21.12.2011

В порядке. Здесь мы видим, что «передача права собственности» происходит в c2 = c3. НО не могу добиться временного создания в static_cast.

static_cast<Circle> (c2); 

будет "украсть" у c2.

person curiousguy    schedule 21.12.2011

У тебя все в порядке с auto_ptr. Как объясняет ответ Стива, язык достаточно умен, чтобы делать это с помощью обычных указателей. Приведение указателя между базовым и производным классами может потребовать изменения значения указателя, и static_cast сделает это при необходимости.

person David Schwartz    schedule 20.12.2011
comment
В порядке. Интересно, как смоделировать ситуацию, когда создается временный объект auto_ptr. В моей скромной симуляции operator = никогда не звонил. Конечно, это не практический вопрос. Это только теоретическое исследование. Опять же, я застрял с имитацией auto_ptr временного создания и вызова оператора присваивания копии. Как видите, класс Circle является грубой симуляцией потери права собственности в auto_ptr. - person nickolay; 21.12.2011
comment
Я не понимаю, что ты пытаешься сделать. - person David Schwartz; 21.12.2011
comment
Пожалуйста, перечитайте тело вопроса. Я добавил некоторые детали. Спасибо! - person nickolay; 21.12.2011

Самое простое, что я мог придумать, это (если вы измените пример в вашем исходном вопросе):

wcout << aS->GetName() << L'\t' << static_cast<auto_ptr<Circle>>(aS.get())->GetRadius() << endl;

Этот :

static_cast<auto_ptr<Circle>>(aS.get())

создает временный объект типа auto_ptr< Circle >, который уничтожает объект типа auto_ptr< Shape > в конце области видимости.

Вот пример (надеюсь, он достаточно ясен):

#include <iostream>
#include <memory>

struct B
{
    ~B()
    {
        std::cout<<"~B"<<std::endl;
    }
    void foo()
    {
        std::cout<<"foo"<<std::endl;
    }
};
struct A : B
{
    ~A()
    {
        std::cout<<"~A"<<std::endl;
    }
    void bar()
    {
        std::cout<<"boom"<<std::endl;
    }
};

int main() {
    std::auto_ptr< A > a( new A );
    {
        std::auto_ptr< B > b( a.get() );
        b->foo();
    }

    std::cout<<"prepare for the crash"<<std::endl;
}
person BЈовић    schedule 20.12.2011
comment
Правильно! Это Стив написал в ответ на мой первоначальный вопрос. Я не могу скомпилировать приведенный выше код (с auto_ptr). Итак, я хотел бы смоделировать такую ​​ситуацию, чтобы отслеживать создание этого временного объекта. Circle класс вместо auto_ptr. Я хотел бы запустить operator = при создании временного во время вызова static_cast. Не могли бы вы помочь мне написать правильный код моделирования? - person nickolay; 21.12.2011
comment
@DaddyM Я добавил еще один пример того, что происходит, но без временного объекта. - person BЈовић; 21.12.2011
comment
@DaddyM: operator= не используется при копировании в приведении, а используется конструктор копирования. Таким образом, нет способа сделать то, что вы, кажется, хотите, а именно получить результат static_cast в вызове operator=. - person Steve Jessop; 21.12.2011
comment
@VJovic Спасибо. Но меня интересует не это. Вы показали, как a попытается вызвать деструктор хранимого объекта, который уже уничтожен b. Мне интересно смоделировать это: static_cast<auto_ptr<Circle>>(aS.get()), но с другим классом UDF (исходный код с auto_ptr не будет работать). - person nickolay; 21.12.2011
comment
@SteveJessop Приятно видеть тебя здесь. Вы меня поняли. Подскажите, пожалуйста, как смоделировать такую ​​ситуацию с классом UDF, который имитирует "потерю права собственности" при копировании во временный static_cast. Все, что меня интересует: трассировка вызовов для копирования ctor при временном создании в static_cast. - person nickolay; 21.12.2011