I have this:
typedef void (*funcptr) (void);
int main(){
funcptr(); //this can compile and run with no error . WHAT DOES IT MEAN? WHY NO ERRORS?
}
The statement creates a funcptr instance by its default constructor* and discard it.
It is just similar to the code
int main () {
double();
}
(Note: * Technically it performs default-initialization as not all types have constructors. Those types will return the default value (zero-initialized), e.g. 0. See C++98 §5.2.3/2 and §8.5/5 for what actually happens.)
In C++ language, any expression of the form some_type() creates a value of type some_type. The value is value-initialized.
For example, expression int() creates a value-initialized value of type int. Value-initialization for int means zero initialization, meaning that int() evaluates to compile-time integer zero.
The same thing happens in your example. You created a value-initialized value of type funcptr. For pointer types, value-initialization means initialization with null-pointer.
(Note also, that it is absolutely incorrect to say that expressions like int(), double() or the one in your OP with non-class types use "default constructors". Non-class types have no constructors. The concept of initialization for non-class types is defined by the language specification without involving any "constructors".)
In other words, you are not really "playing with function pointer" in your code sample. You are creating a null function pointer value, but you are not doing anything else with it, which is why the code does not exhibit any problems. If you wanted to attempt a call through that function pointer, it would look as follows funcptr()() (note two pairs of ()), and this code would most certainly crash, since that's what usually happens when one attempts a call through a null function pointer value.
You are defining a datatype, funcptr, which is a function that takes no parameters and returns void. You are then creating an instance of it, but without an identifier, discarding it.
Related
I am the beginner of learning C++. Today, I saw a pointer function like that
(*(int (*)())a)()
I was very confused with what the meaning of this and how I can understand it easily.
Let's add a typedef, to help make heads or tails out of it:
typedef int (*int_func_ptr)();
(*(int_func_ptr)a)();
So a is being cast to a function pointer of a particular prototype, dereferenced (which is redundant), and then called.
int (*)() is a function pointer type that returns int and accepts no parameters.
I presume that a is a function pointer whose type "erases" the actual type (perhaps so that one can store a bunch of different function pointers in a vector) that we need to cast to this pointer type, so (int(*)())a) will perform that casting.
Afterwards we want to call the function, so the provided code dereferences the pointer * and then calls it with parenthesis ()
Example
I have a function foo that looks like this:
int foo()
{
std::cout << "foo\n";
return 1;
}
And then via reinterpret_cast I get a pointer to a function that instead returns void (for type-erasure reasons):
void(*fptr)() = reinterpret_cast<void(*)()>(&::foo); //§5.2.10/6
Later, I want to call that function, so I need to re-cast it back to its original type, and then call it:
(*(int (*)())fptr)(); // prints `foo`
Demo
De-referencing it is actually unecessary and the following is equivalent:
((int (*)())fptr)();
The explanation for why they're equivalent boils down to "The standard says that both a function type and a function pointer type can be callable"
If you're standard savvy, you can check out §5.2.2[expr.call] that states
A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of initializer-clauses which constitute the arguments to the function. The postfix expression shall have function type or pointer to function type
StoryTeller and Andy have given correct answers. I'll give general rules, additionally.
StoryTeller makes a correct and useful typedef with typedef int (*int_func_ptr)();, which defines a function pointer type. Two things are to remember here.
The general language design for typedefs: it exactly mimics a declaration of an object of the given type! Simply prefixing a declaration with typedef makes the declared identifier a type alias instead of a variable. That is, if int i; declares an integer variable, typedefint i; declares i as a synonym for the type int. So declaring a function pointer variable would simply read int (*int_func_ptr)();. Prefixing this with the typedef, as StoryTeller did, makes it a type alias instead.
Casts of function pointers are notoriously confusing. One reason are the necessary parentheses:
Parentheses serve several unrelated purposes:
They group expressions to indicate subexpression precedence, as in (a+b) * c.
They delimit function arguments, both in declarations and in calls.
They delimit type names used in casts.
We have parentheses for all three purposes here!
The operator precedence is "unnatural" for function pointer declarations. This is so, of course, because they are natural for the much more frequent uses: Without parentheses, the declaration would be the more familiar looking int *int_func();, which declares a function proper which returns an int pointer. The reason is that the argument parentheses have higher priority than the dereferencing asterisk, so that in order to infer the type we mentally execute the call first, and not the dereferencing. And something that can be called is a function.1 The result of the call can be dereferenced, and that result is an int.
Compare that to the original int (*int_func_ptr)();: The additional parentheses force us to dereference first, so the identifier must be a pointer of some kind. The result of the dereferencing can be called, so it must be a function; the result of the call is an int.
Another reason why function pointer declarations or typedefs look unnatural is that the declared identifier tends to be at the center of the expression. The reason is that operators to the left and to the right of the identifier are applied (the dereferencing, the function call, and then there is finally the result type declaration all the way to the left).
The next rule is about constructing casts. The type names used in casts are constructed from corresponding variable declarations simply by omitting the variable name! This is obvious in the simple cases: since int i declares an int variable, (int) without the i is the corresponding cast.
If we apply that to the function pointer type, int (*int_func_ptr)() is transformed to the weird-looking (int (*)()) by omitting the variable name and putting the type name in parentheses as required for a cast. Note that the parentheses which force precedence of the asterisk are still there, even though there is nothing to dereference! Without them, (int *()) would be derived from int *int_func() and therefore denote a function which returns a pointer.2
It is perhaps surprising that there is exactly one place in a declaration where a variable name can syntactically be, so that even very complicated type expressions in casts are well-defined: It is this one place where a variable name fits which defines the cast type.
With these rules, let's re-examine the original expression:
(*(int (*)())a)()
On the outermost level we have two pairs of parentheses. The second pair is empty and thus must be a function call operator. That implies that the operand to the left has function type:
*(int (*)())a
The operand is an expression in parentheses for precedence. It has three parts: The asterisk, an expression in parentheses, and an identifier a. Since there is no operator between the parenthesized expression and the variable a, it must be a cast, actually the one we scrutinized above. * and the type cast have the same precedence and are evaluated right-to-left: first a is cast to a function pointer, and then * dereferences that in order to obtain the "function proper" (which are no real objects in C++). This fits because the function call operator from above will be applied to this result.
1 That C permits calling function pointers directly as well, without dereferencing first, is syntactic sugar and not considered in declarations.
2 While the expression is syntactically valid, such a cast to function is not allowed in C or C++.
As a newbie, I found it quite cryptic about the explanation of returning from function in C++ books.
Here is a summary of my understanding, hopefully someone can correct it:
Premises:
T foo() {
...
return expr;
}
main() {
T var = foo();
}
Is my below understanding about the returning process correct?
The evaluation result of expr is implicitly converted to declared function return type T. This conversion happens within foo();
The converted value above is used to initialize a temporary object, say "x". Sub-Question: Does this second conversion happen within foo() or main()?
The temporary object "x" is used to initialize variable var within main().
Any input is welcome!
Let's approach this systematically.
If a function is declared as T f();, and T is not void, and if the function returns normally, then it must return via a statement of the form return e;, where e is some expression.
When you evaluate the function-call expression f(), you obtain a value. Suppose U denotes an object type. If T = U & or T = U &&, then the value is of type U, the expression e must be able to bind to the reference, and the return value is the value of e. (The return value is also a so-called "glvalue", in terms of its value category). Nothing else happens in this case. The value of the function call is the thing being returned.
However, when T = U, then the value of f() is a so-called "prvalue" (a "pure rvalue"), and this necessitates the construction of a temporary object of type U. This object is constructed as if by U obj = e (i.e. implicitly converted from the e). The value of f() is then this temporary object. It may either be used to initialize yet another object (e.g. U x = f();), or it may be bound to a reference (e.g. U && r = f();).
The binding of the return expression e to the function-call value happens as the last thing inside the function body scope. Notably, this is before the end of the scope, i.e. before scope-local objects are destroyed. For example, if an exception is thrown during the construction of the return value object, scope unwinding has to happen to destroy local objects before the exception passes to the calling scope. Another useful illustration may be in the use of scoped guards, e.g. mutex locks:
U f()
{
std::locK_guard<std::mutex> lock(state_mutex);
return state.get_value();
}
Here we assume that the initialization U obj = state.get_value(); makes sense, and we assume further that state.get_value() must only be called while state_mutex is locked. The above code does this correctly and concisely.
You are correct, the implicit conversion happens within foo. Consider when you have more than one return statement and each one returns a different type - all of those types must be converted before a value can be returned.
There's no second conversion. The first conversion occurs as part of the construction or assignment of the temporary.
Correct, except as explained below.
There's an optimization that many compilers will make called copy elision which skips the temporary altogether.
Your understanding is essentially correct.
There can be some optimizations, so that there are not that many steps of
copying. This can be either in the form of return value optimization or
in c++11 move semantics
Regarding your sub question;
You should make neither assumption, in say custom conversion operators, constructors
destructors, etc.
When using a '&' next to the return type, are you returning a reference, or is it a bit-by-bit copy still?
Example:
T& operator[](const int index)
{
return m_array[index];
}
There is no copy made of m_array[index] - the return is a reference variable to it.
You are never "returning a reference". This is a general sloppiness of expression by people who hopefully know better, but if you're new or unsure, it pays to be accurate: What really happens is that evaluating a function produces a value. Values have types, and those types are always object types (i.e. never references). So a function cannot "return a reference"; a function always "returns a value", if you will. (But it's better to say that "function evaluation produces a value".)
The only question is what that value is. If a function is declared as U f(), where U is an object type, then the value is a temporary, which is passed around by copy (at least nominally). However, if the function is declared as U & f() or U && f(), then the value is some existing object, and no new object is created and passed around. Such function evaluation lets you see some existing object directly, if you will. Colloquially we say that "f returns a reference", but be careful with such language.
In your case, m_array is an existing object, m_array[index] is (presumably) some subobject of that object, and the function evaluation produces that very object (which is presumably some array element).
When using a '&' next to the return type, are you returning a reference, or is it a bit-by-bit copy still?
You are returning a reference to whatever object the function's return statement specifies (so that shouldn't be a temporary, which the leading m_ implies it's not - all good).
Still, returning references to objects is not the opposite of "bit-by-bit copy"... C++ often uses custom copy constructors and/or assignment operators to ensure proper deep copying etc..
I'm a little confused after reading something in a textbook. Regarding the code:
void doSomeWork(const Widget& w)
{
//Fun stuff.
}
doSomeWork(Widget(15));
doSomeWork() takes a const Widget& parameter. The textbook, Effective C++ III, states that this creates a temporary Widget object to pass to doSomeWork. It says that this can be replaced by:
doSomeWork(static_cast<Widget>(15));
as both versions are casts - the first is just a function-style C cast apparently. I would have thought that Widget(15) would invoke a constructor for widget taking one integer parameter though.
Would the constructor be executed in this case?
In C++ this kind of expression is a form of a cast, at least syntactically. I.e. you use a C++ functional cast syntax Widget(15) to create a temporary object of type Widget.
Even when you construct a temporary using a multi-argument constructor (as in Widget(1, 2, 3)) it is still considered a variation of functional cast notation (see 5.2.3)
In other words, your "Is this a cast or a construction" question is incorrectly stated, since it implies mutual exclusivity between casts and "constructions". They are not mutually exclusive. In fact, every type conversion (be that an explicit cast or something more implicit) is nothing else than a creation ("construction") of a new temporary object of the target type (excluding, maybe, some reference initializations).
BTW, functional cast notation is a chiefly C++ notation. C language has no functional-style casts.
Short: Yes.
Long:
You can always test those things yourself, by doing e.g.:
#include <iostream>
struct W
{
W( int i )
{
std::cout << "W(" << i << ")\n";
}
};
int main(int argc, const char *argv[])
{
W w(1);
W(2);
static_cast<W>(3);
}
which is outputting
W(1)
W(2)
W(3)
Yes, it is both :). A cast is a syntactic construct (i.e. something you type). In this case, a constructor is invoked as a consequence of the cast. Much like a constructor would be invoked as a consequence of typing
Widget w(15);
Both Widget(15) and static_cast<Widget>(15) are casts, or conversion
operators, if you prefer. Both create a new object of the designated
type, by converting 15 into a Widget. Since 15 doesn't have any
conversion operators, the only way to do this conversion is by
allocating the necessary memory (on the stack) and calling the
appropriate constructor. This is really no different that double(15)
and static_cast<double>(15), except that we usually don't think of
double as having a constructor (but the resulting double is a new
object, distinct from the 15, which has type int).
You said:
the first is just a function-style C cast apparently
The first would not compile in C, it's not C-style. C-style looks like (Widget)15. Here, the temporary object is created, using Widget::Widget(int).
Therefore, it is not a C-style cast.
Yes, of course. Any constructor takes a single parameter would be considered as CONVERSION CONSTRUCTOR. Your constructor is already taking a single int parameter, so that the compiler can "implicitly" call this constructor to match the argument (with the value 15, which is int).
There is a simple trick to prevent such errors, just use the keyword explicit before your constructor.
Check this for more information.
Yeeeah. You can replace
Widget(15)
with
static_cast<Widget>(15)
Because it will be replaced back by compiler :D
When you cast int to Widget compiler looks for Widget::Widget(int); and place it there.
I understand from the answer to this question that values of global/static uninitialized int will be 0. The answer to this one says that for vectors, the default constructor for the object type will be called.
I am unable to figure out - what happens when I have vector<int> v(10) in a local function. What is the default constructor for int? What if I have vector<int> v(10) declared globally?
What I am seeing is that vector<int> v(10) in a local function is resulting in variables being 0 - but I am not sure if that is just because of my compiler or is the fixed expected behaviour.
The zero initialization is specified in the standard as default zero initialization/value initialization for builtin types, primarily to support just this type of case in template use.
Note that this behavior is different from a local variable such as int x; which leaves the value uninitialized (as in the C language that behavior is inherited from).
It is not undefined behaviour, a vector automatically initialises all its elements. You can select a different default if you want.
The constructor is:
vector( size_type, T t = T() )
and for int, the default type (returned by int()) is 0.
In a local function this:
int x;
is not guaranteed to initialise the variable to 0.
int x = int();
would do so.
int x();
sadly does neither but declares a function.
The constructor you are using actually takes two arguments, the second of which is optional. Its declaration looks like this:
explicit vector(size_type n, const T& value = T())
The first argument is the number of elements to create in the vector initially; the second argument is the value to copy into each of those elements.
For any object type T, T() is called "value initialization." For numeric types, it gives you 0. For a class type with a default constructor, it gives you an object that has been default constructed using that constructor.
For more details on the "magic parentheses," I'd recommend reading Michael Burr's excellent answer to the question "Do the parentheses after the type name make a difference with new?" It discusses value initialization when used with new specifically, but for the most part is applicable to value initialization wherever else it can be used.
By default, vector elements are zero-initialized and not default-initialized. Those are two different but related concepts:
zero-initialization is what is done for static objects not having an explicit initialization and what is done for a member given in the initialized list with an initializer of (). For basic types, the value used is 0 converted to the type.
default-initialization is what is done for not explicitly initialized non static variables and members. For basic types it stay uninitialized.
(And C++0X introduces value-initialization which is still different).
As mentioned by others, what happens is the zero initialization kicks in. I actually use that a lot in my code (outside of vectors and other classes):
some_type my_var = some_type();
This allows me to make sure that my variables are always properly initialized since by default C/C++ do not initialize basic types (char, short, int, long, float, double, etc.)
Since C++11, you also can do so in your class definitions:
class MyClass
{
...
int my_field_ = 123; // explicit initialization
int your_field_ = int(); // zero initialization
};
For vectors, the std library uses T(). Whatever T() is, it will use that default initialization. For a class, it calls the default constructor. For a basic type, it uses zero ('\0', 0, 0.0f, 0.0, nullptr`).
As mentioned by James McNellis and Nawaz, it is possible to set the value used to initialize the vector as in:
std::vector<int> foo(100, 1234);
That feature is also available when you resize your vector (if the vector shrinks, the default value is ignored):
foo.resize(200, 1234);
So that way you can have a default initialization value. However, it's a be tricky since you have to make sure that all your definitions and resize() calls use that default value. That's when you want to write your own class which ensures that the default value is always passed to the vector functions.
However, if you want to have a way to auto-initialize to a specific value, you can mix both features this way:
struct my_value {
int v = 123;
};
std::vector<my_value> foo(100);
// here foo[n].v == 123 for n in [0, 100)
This is my preferred way of dealing with this issue (i.e. if I don't want zero by default). It's an extra .v, but much less prone to mistakes and you don't need to know of the default value when you create a vector of my_value.
Also, for those who think this will be slow, it won't. The struct is like syntactic sugar as far as C++ is concerned. One optimized, it will be exactly the same as a simple std::vector<int> foo(100, 123).
The default initialization for an int type is to initialize it to 0.
This is true of most (if not all) primitive types: char will initialize to (char)0 (or '\0' if you prefer), float will initialize to 0.0f, and any pointer initializes to NULL. For other types, the parameterless constructor is invoked.
In general, the default initialization should happen pretty much whenever you aren't able to specify a constructor (or choose not to).