What is the element value in an uninitialized vector? - c++

If I create a vector like vector<myClass> v(10);
what is the default value of each element?
Also, what if it is a vector<myUnion> v(10) ?

The constructor of std::vector<> that you are using when you declare your vector as
vector<myClass> v(10);
actually has more than one parameter. It has three parameters: initial size (that you specified as 10), the initial value for new elements and the allocator value.
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
The second and the third parameters have default arguments, which is why you were are able to omit them in your declaration.
The default argument value for the new element is the default-contructed one, which in your case is MyClass(). This value will be copied to all 10 new elements by means of their copy-constructors.
What exactly MyClass() means depends on your class. Only you know that.
P.S. Standard library implementations are allowed to use function overloading instead of default arguments when implementing the above interface. If some implementation decides to use function overloading, it might declare a constructor with just a single parameter (size) in std::vector. This does not affect the end result though: all vector elements should begin their lives as if they were value-initialized.

vector<myClass> v;
its a empty vector with size and capacity as 0.

The answer to your second question is similar; vector<myUnion> v(10) will create an array of 10 myUnions initialized with their default constructor. However note that: 1) Unions can't have members with constructors, copy constructors or destructors, as the compiler won't know which member to construct, copy or destroy, and 2) As with classes and structs, members with built-in type such as int will be initialized as per default, which is to say not at all; their values will be undefined.

Related

Is the initialization order of the vector elements guaranteed by the standard?

To fill a std::vector<struct_name> from std::cin, I usually write as following code:
struct point{
int x, y;
};
int main()
{
std::size_t n;
std::cin>>n;
std::vector<point> vec(n);
for (auto& p:vec)
std::cin>>p.x>>p.y;
//...
}
But today I found out another way to do it with default constructor:
struct point{
int x, y;
point(){
std::cin>>x>>y;
}
};
int main()
{
std::size_t n;
std::cin>>n;
std::vector<point> vec(n);
//...
}
Questions:
Is the initialization order of the vector elements guaranteed by the standard(0,1,2,n-1...)?
(If answer of previous question is true) Is really the second variant has twice effective?
I am interested in behavior according to the C++11(and newer) standard
It is not guaranteed that the elements are initialized in the order of their indices. In C++11, see [vector.cons]/3:
Effects: Constructs a vector with n value-initialized elements.
This says nothing about the ordering, so nothing can be assumed. The wording changes in later editions of the standard, but no ordering ever seems to have been imposed.
On your first question, the C++20 (but this goes back to C++11 as well) section dealing with the vector sequence container makes no promises about the order in which elements are constructed within the vector itself, only that the elements are set to some specific value:
Effects: Constructs a vector with n default-inserted elements.
Nothing at all about the order in that (very brief) section(a).
But you have a bigger problem with your method, specifically I don't think you really want to go out to cin for every case where you're default constructing a point variable.
There may be, for example, cases where you need a default-constructed temporary variable and it's going to be seen as a hang if your program suddenly stops to accept user input, especially without some prompt to the user :-)
That makes your second question moot but, assuming you're concerned about inefficiencies in initialising vector elements then changing them with an input loop, I wouldn't be. The structure with no constructor (i.e., just a couple of int variables) doesn't need to initialise them(b), so a vector of them can just do the allocation and stop there.
(a) Some order is guaranteed in the standard, such as the order of disparate members within a class, or the order of elements within an array. However, the elements of a vector are neither of those things.
(b) This is covered in C++20 10.9 Iniitialisation [class.init]:
When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form (), the object is initialized as specified in 9.3.
and C++20 9.3 Initializers [dcl.init]:
To default-initialize an object of type T means:
If T is a (possibly cv-qualified) class type, constructors are considered. The applicable constructors are enumerated, and the best one for the initializer () is chosen through overload resolution. The constructor thus selected is called, with an empty argument list, to initialize the object.
If T is an array type, each element is default-initialized.
Otherwise, no initialization is performed.
It's that first bullet point that kicks in for a type with no constructors explicitly defined or inherited. In that case, it uses the implicitly-defined constructor which is equivalent to a user defined constructor with no body and no initialiser list.

Initialization of vectors

When I execute the following statement:
vector <int> v;
What exactly will the value of v be?
Will it just be a pointer that points to the start of a memory block? Will its value be NULL?
Some points to possible duplicates to another question which is more complicated than this one, and focus less on the comparison of 1) calling the default constructor of vector class and 2) initialization of an array which I believe is a pointer to int.
Your syntax will call the constructor with no parameters, also known as the default constructor. According to the std::vector constructor documentation, you can see that it will create an empty vector.
The pointer where it points to does not matter since you are not supposed to dereference its values while the container is empty. Please note that if you want to store the value of the internal pointer, such as std::vector::data(), it may change anytime you add an element to the vector (well, technically, you can predict when the pointer will change, but it’s a good practice to do as if the pointer always changes).
What exactly will the value of v be?
pointer? - no.
NULL - no.
nullptr - no.
v is an instance of class std::vector<T> (where T is int).
On Ubuntu Linux 64 bit, a "std::vector<T> tVec;" occupies 24 bytes regardless of
sizeof(T),
or
number of elements.
The guts of the object are not similar to an array of int, but the implementation does maintain an array of T, probably in dynamic memory.
For each compiler, the implementation may vary.
vector <int> v;
What exactly will the value of v be?
That is the syntax of default initialisation. Therefore the object will be in a default initialised state. For class types such as std::vector, default initialisation calls the default constructor. An online reference describes the default constructor of vector thusly:
1) Default constructor. Constructs an empty container. If no allocator is supplied, allocator is obtained from a default-constructed instance.
Will it just be a pointer that points to the start of a memory block? Will its value be NULL?
A vector is not a pointer.
Among other members, a vector implementation does contain a pointer which may point to a buffer that the vector manages - you can get a copy of that pointer using the std::vector::data member function. The state of the internal pointer of a default initialised vector is unspecified. Since an empty vector does not need a buffer, that pointer may be null - but is not required to be.

Default value of std::vector for base types

I was trying find out how to inialize an std::vector<Object *> with a fixed size, because I don't need to change it anymore afterwards. So I'm using this code (the vector is empty before):
mControllerItem.resize(nLines, nullptr);
According to the documentation the second element can be used to specify a default which will be copied into the new elements, but this is optional. If no second argument is given, then the default constructor is used.
In case of base types like pointer, int, etc.., what is used here? In the link it doesn't say anything about it. Will they be initialized to 0, do they stay undefined, or is there some other mechanism which determines what values they will get? In the example on the link the output is 0, so I assume that it is iniatliezed with that, but is this guaruanteed, or is this implementation (or un)defined?
The standard stipulates that resize will value-initialize any items that need to be inserted, so the behavior here is perfectly well defined.
In simple terms, value-initialization means:
for class types, the default constructor is called; if no constructor has been provided, then each member is value-initialized (recursively)
for scalars of any type T, they are given the value (T)0 (this guarantees that if T is a pointer the value used will be null portably)
The behavior is defined slightly different between C++03 and C++11. In the former, a value-initialized object is created and the new elements in the vector are copy-constructed from that. In the new version, the new elements are value-initialized directly.
For built-in types like pointers, value-initialization equals zero-initialization, so your elements are, in-fact, guaranteed to be zero for both versions of the standard.
Note that your assumption that the default-constructor is used is actually not quite correct. It is, but only for custom types. It just happens that the syntax for value-initialization calls the default constructor for custom types, and zero-initializes for built-in types.
Yes in case of pointers they will be initialized bu nulls. All base types have default constructors. The only difference is following
int a; // default constructor will not be called so value is
undefined
class C {int a; C(): a()}; // default constructor will be called and value will be 0
void f(int a = int()) // default constructor will be called and value will be 0

Why are vector's multi-argument constructors taking construction parameters not marked "explicit"?

I observed the following vector constructors in the Standard C++ library
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
Is there a reason why the second constructor is not marked explicit? This compiles, and makes me feel bad
void f(vector<string>);
int main() {
f({10, "foo"});
}
While if I omit the "foo", it doesn't compile and that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.
I'm wondering whether it is legitimate in the first place to expect that { ... } always represents a list of container elements when creating a temporary. This seems to be your assumption. IMO the one-argument constructor needs to be declared as explicit to avoid undesidered conversion sequences or meaningless assignments such as:
vector<int> x = 3;
On the other hand, for the two-argument version, the only way this constructor can be called when a temporary is created is with the use of curly braces, and the programmer is well aware of what he's putting in there. For instance, it is quite clear to me that 10 and "hello" are not meant to represent a list of container elements, because 10 is not a string.
If I really wanted to pass in a vector of 10 elements initialized to "hello", I would be bothered by having to write f(vector(10, "hello")) instead of just doing f({10, "hello"}).
So to sum it up: while the one-argument constructor needs to be declared as explicit, I believe this is not mandatory for the two-argument value, because not everything which is inside a pair of curly braces should be interpreted as a list of container elements.
While if I omit the "foo", it doesn't compile and that is what I expect
when I pass a pair (compound) value of an int and a string to a function that wants
a vector of strings.
No, you don't pass a pair of int and a string but you create a vector of size 10 with content of strings like "foo". There is nothing wrong on it! I can figure some situation where it may be usefull to create a vector contains the equal strings from the beginning.
that is what I expect when I pass a pair (compound) value of an int and a string to a function that wants a vector of strings.
Well, there's your problem.
{...} is not a "compound value". It is not a list. It says, "initialize an object using these values". If the object in question is an aggregate, it will use aggregate initialization. If the object in question is a non-aggregate type, it will pick a constructor to call, based on the matching constructors of the type and the various rules for braced-init-lists in C++11.
You shouldn't think of {10, "foo"} as a list of two values. It is an initializer that contains two values. It could be used with a std::pair<int, const char *>, and so forth.
The reason why std::vector's constructor isn't explicit is precisely to allow this construct. The single-argument constructor is explicit because otherwise, implicit conversion rules would allow this:
std::vector<T> v = 5; //???
Or, more importantly:
void Foo(const std::vector<T> &v);
Foo(5); //???
We don't want integers to be implicitly convertible to std::vectors. However, when you're using an initializer, it's more reasonable to allow a wider range of "implicit" conversions, because you can see the {} syntax there.
With the single-argument case, it isn't clear what the user means. With the {} syntax, it is clear what the user means: to initialize the object.
Foo({10, "foo"}); //Initializes the first argument given the values.

std::vector elements initializing

std::vector<int> v1(1000);
std::vector<std::vector<int>> v2(1000);
std::vector<std::vector<int>::const_iterator> v3(1000);
How elements of these 3 vectors initialized?
About int, I test it and I saw that all elements become 0. Is this standard? I believed that primitives remain undefined. I create a vector with 300000000 elements, give non-zero values, delete it and recreate it, to avoid OS memory clear for data safety. Elements of recreated vector were 0 too.
What about iterator? Is there a initial value (0) for default constructor or initial value remains undefined? When I check this, iterators point to 0, but this can be OS
When I create a special object to track constructors, I saw that for first object, vector run the default constructor and for all others it run the copy constructor. Is this standard?
Is there a way to completely avoid initialization of elements? Or I must create my own vector? (Oh my God, I always say NOT ANOTHER VECTOR IMPLEMENTATION)
I ask because I use ultra huge sparse matrices with parallel processing, so I cannot use push_back() and of course I don't want useless initialization, when later I will change the value.
You are using this constructor (for std::vector<>):
explicit vector (size_type n, const T& value= T(), const Allocator& = Allocator());
Which has the following documentation:
Repetitive sequence constructor: Initializes the vector with its content set to a repetition, n times, of copies of value.
Since you do not specify the value it takes the default-value of the parameter, T(), which is int in your case, so all elements will be 0
They are default initialized.
About int, I test it and I saw that all elements become 0. Is this standard? I believed that primitives remain undefined.
No, an uninitialized int has an indeterminate value. These are default initialized, i.e.,
int i; // uninitialized, indeterminate value
int k = int(); // default initialized, value == 0
In C++11 the specification for the constructor vector::vector(size_type n) says that n elements are default-inserted. This is being defined as an element initialized by the expression allocator_traits<Allocator>::construct(m, p) (where m is of the allocator type and p a pointer to the type stored in the container). For the default allocator this expression is ::new (static_cast<void*>(p)) T() (see 20.6.8.2). This value-initializes each element.
The elements of a vector are default initialized, which in the case of POD types means zero initialized. There's no way to avoid it with a standard vector.