default initialization and assignment for classes

My questions concern the default initialization, and assignment operations. These examples come from B. Stroustrup’s Programming Principles and Practice using C++ section 19.3 (though this is not the topic of that section).

From what I understand the default initialization operator for a class or struct will wholesale copy elements from the right hand side (rhs) onto the left hand size (lhs). It doesn’t matter how the class is organized, whether the elements are arrays or bools or whatever. The same is true for the default assignment operator; all the data of the rhs is assigned to the lhs. In the example below, the main member is a constant array; in the struct, these elements are copied over for the default assignment and initialization. It looks like this is much different that the behavior for a simple array such as int arr[]. In that case only the pointer can be copied and the members are not copied at all. You can't make an assignment such as int b[] = arr as below. Does the default memberwise copy do whole sale copying?


To initialize a structure such as intstore below would normally require a list of starting values such as {8, 9, 10} below. To initialize the array struct with is int [] member it would normally require {{1, 2, 3}} following the same syntax. Why then does {1, 2, 3} work to initialize the structure?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <iostream>

const int MAX_SIZE = 3;
struct array{
	int elem[MAX_SIZE];
	const int& operator[] (int n) const{ return elem[n]; }
};
struct intstore{
	int a, b, c;
};

std::ostream& operator<< (std::ostream& ostr, const  int* inval)
{
	for (int i = 0; i < MAX_SIZE; ++i)
		ostr << inval[i] << '\t';
	ostr << std::endl;
	return ostr;
}
std:: ostream& operator<<(std::ostream& ostr, const array inval)
{
	for (int i = 0; i < MAX_SIZE; ++i)
		ostr << inval[i] << '\t';
	ostr << std::endl;
	return ostr;
}
int main()
{
	array u = { 1, 2, 3 };// doesn't have to be {{1, 2, 3}}
	array p = u;
	array z;
	z = p;
	std::cout << u << p << z;
	int arr[] = { 4, 5, 6 };
	std::cout << arr;
	intstore is = { 8, 9, 10};
	//int arrb [] = arr; doesn't work-- can't copy arrays
	return 0;
}


output:

1 2 3
1 2 3
1 2 3
4 5 6
A C++ array is based off of a C array, which is not a class. Therefore, you cannot apply the same initialization and assignment semantics to an array as you can with an object of a class. The reason you're able to get away with not having an outer set of braces in the assignment array u = { 1, 2, 3 }; is by design. In fact, you could even assign multiple arrays with just a comma-separated list of values and no inner brackets whatsoever.

Once you've wrapped an array in a struct or class in C++, the default copy constructor and assignment operators are generated for you, and they behave as you stated above. The default operations only perform a shallow copy because there is no way for C++ to know the intent of the programmer when dealing with memory referenced by a pointer.
Thank you for this explanation. It helped a great deal.

In hingsight it is now pretty clear that the comma separated list even without inner brackets is specific enough; each element will be typechecked to see whether it can be converted to the type requested. There really isn't any ambiguity...

Thank you again,

Topic archived. No new replies allowed.