In C# I know you can use the default keyword to assign default values as 0 to value types and null to reference types and for struct types individual members are assigned accordingly. To my knowledge there are no default values in C++. What approach would you take to get the same functionality as the default keyword for Generics while programming in C++?
Use a default constructor, it's used even if you leave off the ()
at the end:
#include <iostream>
class MyClass {
public:
int x;
MyClass(){
x = 5;
}
};
int main(){
MyClass y;
std::cout << y.x;
}
In C++, assigning a default value to a variable in global scope or in a function is as simple as:
int myint=2;
float* pfloat=NULL;
For class members, you need to initialise these in the class's constructor:
class myclass {
private:
int i;
public:
myclass() {
i = 4;
}
};
I'm not sure about structures.
Assuming the type is default-constructible, you can use value initialization. For example,
template <typename T>
T get()
{
return T(); // returns a value-initialized object of type T
}
If the type is not default-constructible, typically you need to provide a default to use. For example,
template <typename T>
T get(const T& default_value = T())
{
return default_value;
}
This function can be called with no argument if the type is default-constructible. For other types, you can provide a value to be returned.
C++ doesn't have the default
keyword, because it doesn't have the distinction between reference and value types. In C++, all types are what C# would consider value types, and if they're default constructible (as built-in types, POD structs and class types with default constructors are), they are initialized using value initialization (the default constructor syntax), as James McNellis showed: (and shamelessly copied here)
template <typename T>
T get()
{
return T(); // returns a value-initialized object of type T
}
if T
has a default constructor, it is invoked. If it has no constructors, everything is initialized to zero/null.
And if the type is not default constructible, there is no default value the object could be given.
Here is a quick summary of initialization techniques in C++03.
To zero-initialize an object of type T means: — if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
— if T is a non-union class type, each nonstatic data member and each base-class subobject is zeroinitialized; — if T is a union type, the object’s first named data member89) is zero-initialized; — if T is an array type, each element is zero-initialized; — if T is a reference type, no initialization is performed.
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is an array type, each element is default-initialized; — otherwise, the object is zero-initialized.
To value-initialize an object of type T means: >
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor); — if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized; — if T is an array type, then each element is value-initialized; — otherwise, the object is zero-initialized
With that understanding
struct S{
int x;
S():x(1){}
};
S sg; // Every object of static storage duration is zero initialized at program startup before any other initialization takes place. So 'x' is initialized to 0, before the default constructor runs and sets 'x' to 1.
int main{
int x = int(); // value initialization syntax, as per rules above is initialized to 0.
S sl; // default initialized
}
In C++, you'd typically invoke the default constructor (the constructor that may be called with no arguments). This works for primitive types too (that is, int()
is 0, int*()
is the null pointer, etc.).
For example, in your template function, you'd write something like:
template<typename T>
T foo()
{
T x = T(); // See notes below about this.
// Do other stuff.
return x;
}
Note that T x;
by itself would be sufficient to implicitly invoke a default constructor for non-POD types, but that wouldn't work for primitive scalar types (such as int
) where it would be initialized to garbage. (T x()
also wouldn't work; that would be interpreted as a function declaration.)
This is good question. The pletora of c++ type variations makes writing safe templates of the kind as below a pain.
template <typename T> struct FrameworkTemplate {
T mInstance;
};
Consider that, in theory, the user might instantiate your class template as
// assume A is a known default constructible type
FrameworkTemplate<A>
FrameworkTemplate<const A>
FrameworkTemplate<A const *>
FrameworkTemplate<A const &> // and so on
where the last three are not default constructible, though A might be. That's why useful generic types like any
, nullable
, lazy
and so on, though simple and intuitive at the first sight, are non trivial to implement (safely) in c++...