1

Please take a look at this code snippet

#include <iostream>
using namespace std;

class foo{
    public:
    virtual void v1(){
        std::cout << "In Base this:" << std::hex << this << "\n";   
    }
};

class bar:public foo{
    public:
    void v1() {
        std::cout << "In Derived this:" << std::hex << this << "\n";
    }
};

int main() {
    bar a, b, c;
    static_cast<foo*>(&a)->v1();
    static_cast<foo*>(&b)->v1();
    static_cast<foo*>(&c)->v1();
    static_cast<foo>(b).v1();
    static_cast<foo>(b).v1();
    return 0;
}

The output is

In Derived this:0x7ffe8a9e8890
In Derived this:0x7ffe8a9e88a0
In Derived this:0x7ffe8a9e88b0
In Base this:0x7ffe8a9e88c0
In Base this:0x7ffe8a9e88c0

As evident from value of this pointer static_cast<foo>(b) creates a completely new variable.

Moreover, further calls to static_cast<foo>(b) refer to the previously created variable.

Could someone explain this behavior.

EDIT: From the comments I get why static_cast<foo>(b) would create a new variable. Still what I could not understand is that why multiple calls to static_cast<foo>(b) refer to the same variable. Is is a compiler optimization ?

Nishant
  • 2,571
  • 1
  • 17
  • 29
  • The static_cast can use implicit conversion and/or constructors to do the work. You have state-less objects in your example, I am affraid that is too simple to really show how static_cast works. – Al Kepp Sep 28 '17 at 23:47
  • This is not a duplicate of "what is object slicing". There is a cast which creates a temporary @Slava. – alain Sep 28 '17 at 23:48
  • 1
    @alain and that temporary has which type? And you want to say that slicing is not involved? What the difference with foo tmp = b; and `static_cast(b)` ? – Slava Sep 28 '17 at 23:50
  • How can slicing be involved when there are no data in these objects? – Al Kepp Sep 28 '17 at 23:53
  • 1
    @AlKepp how about vtable? Again do the same with assignemnt to `foo` or pass to a function accepting `foo` and you will have exactly the same behaviour. – Slava Sep 28 '17 at 23:54
  • @Slava I would have bet this code is not UB, but you make me unsure now... – alain Sep 28 '17 at 23:55
  • @alain slicing may have unexpected to someone behaviour, but it is defined. – Slava Sep 28 '17 at 23:57
  • Yes this is not UB, you can use a derived as a base, and using it as a base includes making a temporary copy as a base. And OP's question is about that temporary. Would you reopen? – alain Sep 28 '17 at 23:57
  • 1
    @alain that temporary has base type and assigning to it involves slicing, hance observed behavior, why to reopen? – Slava Sep 29 '17 at 00:01
  • @Slava I'm not saying this is not a duplicate, but the slicing question deals with things like trying to insert deriveds into a vector or bases and expecting to retrieve deriveds. This question sounds more like "what is this new object I get when I cast" to me. – alain Sep 29 '17 at 00:11
  • `static_cast` will create a new variable, this is how the language works. If you don't want that, use a cast to reference. `static_cast`. Your other observation is false. `static_cast(b)` doesn't refer to the same variable. There is a destructor+constructor call in between. The addresses of these variables are the same, but "logically", they are different objects. – geza Sep 29 '17 at 00:12
  • @geza I understand that this type of cast creates a new object and there is a constructor call in between. Even then, why multiple static_casts refer to the same object, is this a compiler optimization ? – Nishant Sep 29 '17 at 00:24
  • It's the same address but not the same object. The rvalue is probably on the stack, this would explain why the same address is reused. If you create something on the stack and destroy it, then create the same thing again, you get the same address. – alain Sep 29 '17 at 00:29
  • @Nishant: you may consider this an optimization. As I've said, they are not the same objects. First, `static_cast` will construct an object on the stack, then it will be destroyed. Then, the 2nd `static_cast` will construct another one, and this one will be destroyed too. As these objects lifetime are different (non-overlapping), they can be placed at the same location. A not-very-dumb compiler will do this, so I don't consider this an optimization. – geza Sep 29 '17 at 00:30

0 Answers0