0

I wonder - what are cast result in cpp actualy is? And specificly - what are their lifetime?

Consider this example:

#include <iostream>
#include <stdint.h>

using namespace std;

class Foo
{
public:
    Foo(const int8_t & ref)
    : _ptr(&ref)
    {}

    const int8_t & getRef() { return *_ptr; }

private:
    const int8_t * _ptr;
};


enum Bar
{
    SOME_BAR = 100
};

int main()
{
    {
        int32_t value = 50;
        Foo x(static_cast<int16_t>(value));
        std::cout << "casted from int32_t " << x.getRef() << std::endl;
    }


    {
        Bar value = SOME_BAR;
        Foo x(static_cast<int16_t>(value));
        std::cout << "casted from enum " << x.getRef() << std::endl; 
    }

   return 0;
}

Output:

casted from int32_t 50
casted from enum 100

It works - but is is safe? With integers i can imagine that compiller somehow cast a "pointer" to needed part of target variable bytes. But what happens when you cast int to float?

Vasilly.Prokopyev
  • 856
  • 1
  • 10
  • 24
  • 4
    You do not have any `static_cast`s in your code. c-style cast != `static_cast`, although the end result *in this particular case* is the same. – user657267 Jul 23 '14 at 05:52
  • You should prefer the more verbose `static_cast< result_type >( source_value )` form vs. `(result_type)source_value` form for the simple reason that it is possible to grep for `static_cast`. – Khouri Giordano Jul 23 '14 at 05:54
  • @user657267 Edited. Sure, static_cast != c-cast. That was just to shorten the example – Vasilly.Prokopyev Jul 23 '14 at 05:55
  • @undefinedhero it didn't "shorten the example", it just made your question confusing. – user657267 Jul 23 '14 at 05:57

1 Answers1

2

static_cast creates an rvalue that exists for the life of the expression. That is, up until the semi-colon. See Value Categories. If you need to pass a reference to the value, the compiler will put the value on the stack and pass that address. Otherwise, it will probably stay in a register, especially with optimizations turned on.

The way you are using it, at the place you're using it, static_cast is completely safe. In the Foo class however, you are saving a pointer to the rvalue. It is only luck that the program executes correctly. A more complex example will probably reuse those stack locations for other uses.

Edited to elaborate on safety of static_cast.

Khouri Giordano
  • 1,426
  • 15
  • 17
  • 1
    +1 for the first part, -1 for the second. It is not safe. He's storing a pointer to the r-value integer. And then dereferencing that pointer later, when the integer no longer exists. – Benjamin Lindley Jul 23 '14 at 05:59
  • 1
    From the Value Categories, link to whom You provided: _An rvalue may be used to initialize a const lvalue reference, in which case the lifetime of the object identified by the rvalue is extended until the scope of the reference ends._ So, if I use a reference insted of poiter in class Foo - will it be safe then? – Vasilly.Prokopyev Jul 23 '14 at 06:06
  • Not the way you used the pointer in Foo. A reference is like a pointer you can only initialize and not change after that. If Foo is documented to retain a pointer or reference to the object that is passed to it, then it is the caller's responsibility to ensure the object outlives the Foo object. I would review this design carefully to see if there were a way to do it that was [easy to use correctly and hard to use incorrectly](http://programmer.97things.oreilly.com/wiki/index.php/Make_Interfaces_Easy_to_Use_Correctly_and_Hard_to_Use_Incorrectly). – Khouri Giordano Jul 23 '14 at 06:13
  • @undefinedhero Related question: http://stackoverflow.com/questions/2604206/c-constant-reference-lifetime – juanchopanza Jul 23 '14 at 06:16
  • `static_cast` results in a _prvalue_ in this case but in general, it can result in a _glvalue_ if the type used is some sort of reference type. – CB Bailey Jul 23 '14 at 06:29