Say I had the lines:
double d = 1.1; auto a = int(d); auto b = static_cast<int>(d);
I understand that I'm doing a cast of a double to an in for the creation of variable b, but is that also happening as well for the creation of a? If I can use is as a shorthand for doing static casts, I'd love to. But if that constructor style variable creation isn't actually doing a static cast, I'd like to know too.
EDIT:
I would say this is my favourite answer of the bunch: https://www.reddit.com/r/cpp_questions/comments/i76d6e/is_static_castxy_the_same_as_xy_for_simple_data/g119fnu/
The difference is that (int)foo can mean half a dozen different things. It might be a static_cast (convert between statically known types), it might be a const_cast (adding or removing const-ness), or it might be a reinterpret_cast (converting between pointer types)
The compiler tries each of them until it finds one that works. Which means that it may not always pick the one you expect, so it can become a subtle source of bugs.
Further, static_cast is a lot easier to search for or do search/replace on.
Look at what Stroustrup has to say about that, including the following:
Because the C-style cast (T) can be used to express many logically different operations, the compiler has only the barest chance to catch misuses. [...]
The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors. [...]
In particular, C++ makes the distinction between static_cast and reinterpret_cast:
The idea is that conversions allowed by static_cast are somewhat less likely to lead to errors than those that require reinterpret_cast. In principle, it is possible to use the result of a static_cast without casting it back to its original type, whereas you should always cast the result of a reinterpret_cast back to its original type before using it to ensure portability.
int vs. typecast - C++ Forum
static_cast vs (int)....
static_cast vs (int)....
Why use static_cast over C style cast for primitive data types?
Videos
The main reason is that classic C casts make no distinction between what we call static_cast<>(), reinterpret_cast<>(), const_cast<>(), and dynamic_cast<>(). These four things are completely different.
A static_cast<>() is usually safe. There is a valid conversion in the language, or an appropriate constructor that makes it possible. The only time it's a bit risky is when you cast down to an inherited class; you must make sure that the object is actually the descendant that you claim it is, by means external to the language (like a flag in the object). A dynamic_cast<>() is safe as long as the result is checked (pointer) or a possible exception is taken into account (reference).
A reinterpret_cast<>() (or a const_cast<>()) on the other hand is always dangerous. You tell the compiler: "trust me: I know this doesn't look like a foo (this looks as if it isn't mutable), but it is".
The first problem is that it's almost impossible to tell which one will occur in a C-style cast without looking at large and disperse pieces of code and knowing all the rules.
Let's assume these:
class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;
CMyBase *pSomething; // filled somewhere
Now, these two are compiled the same way:
CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked
pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read
However, let's see this almost identical code:
CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!
As you can see, there is no easy way to distinguish between the two situations without knowing a lot about all the classes involved.
The second problem is that the C-style casts are too hard to locate. In complex expressions it can be very hard to see C-style casts. It is virtually impossible to write an automated tool that needs to locate C-style casts (for example a search tool) without a full blown C++ compiler front-end. On the other hand, it's easy to search for "static_cast<" or "reinterpret_cast<".
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.
That means that, not only are C-style casts more dangerous, but it's a lot harder to find them all to make sure that they are correct.
One pragmatic tip: you can search easily for the static_cast keyword in your source code if you plan to tidy up the project.
C style cast are faster to write and I prefer them when dealing with basic types. I find it annoying to write static_cast<double>(my_int) just so I can cast something to double for whatever the reason.
Are there any benefits of using statics_cast over C style cast for basic types?
First, understand that those lines are not equivalent.
int* anInt = (int*)aFloat; // is equivalent to
int* anInt = reinterpret_cast<int*>(aFloat);
What is happening here is that the programmer is asking the compiler to do whatever it can to make the cast.
The difference is important because using static_cast will only ask for a base type that is "safe" to convert to, where reinterpret_cast will convert to anything, possibly by just mapping the wanted memory layout over the memory of the given object.
So, as the "filter" is not the same, using a specific cast is more clear and safe than using the C cast. If you rely on the compiler (or runtime implementation if you use dynamic_cast) to tell you where you did something wrong, by avoid using C cast and reinterepret_cast.
Now that this is more clear, there is another thing: static_cast, reinterpret_cast, const_cast and dynamic_cast are easier to search for.
And the ultimate point: they are ugly. That's wanted. Potentially buggy code, code smells, obvious "tricks" that might generate bugs, are easier to track when it's associated with ugly look. Bad code should be ugly.
That's "by design". And that allows the developer to know where he could have done things better (by totally avoiding casts, if not really needed) and where it's fine but it's "documented" in the code by "marking" it as ugly.
A secondary reason for introducing the new-style cast was that C-style casts are very hard to spot in a program. For example, you can't conveniently search for casts using an ordinary editor or word processor. This near-invisibility of C-style casts is especially unfortunate because they are so potentially damaging. An ugly operation should have an ugly syntactic form. That observation was part of the reason for choosing the syntax for the new-style casts. A further reason was for the new-style casts to match the template notation, so that programmers can write their own casts, especially run-time checked casts.
Maybe, because static_cast is so ugly and so relatively hard to type, you're more likely to think twice before using one? That would be good, because casts really are mostly avoidable in modern C++.
Source: Bjarne Stroustrup (C++ creator)
C++ casts are more restrictive (so express your intent better and make code review easier, etc.). They're also much easier to search for, if you ever need to.
There should be no difference at all if you compare int() to equivalent functionality of static_cast<int>().
Using VC2008:
double d = 10.5;
013A13EE fld qword ptr [__real@4025000000000000 (13A5840h)]
013A13F4 fstp qword ptr [d]
int x = int(d);
013A13F7 fld qword ptr [d]
013A13FA call @ILT+215(__ftol2_sse) (13A10DCh)
013A13FF mov dword ptr [x],eax
int y = static_cast<int>(d);
013A1402 fld qword ptr [d]
013A1405 call @ILT+215(__ftol2_sse) (13A10DCh)
013A140A mov dword ptr [y],eax
Obviously, it is 100% the same!
No difference whatsoever.
When it comes to such basic constructs as a single cast, once two constructs have the same semantic meaning, their performace will be perfectly identical, and the machine code generated for these constructs will be the same.