C++ Copy assign

Let's say I have this:
int a = 22;

Now, does "int b = a;" create a copy of the entire object and all it's members or just "22"? If it creates a copy of the entire thing I guess it can slow things down if I have alot of copies instead of pointers/ref in my program?


Also..
If I change the value of "a" to "3" (a = 3) the constructor gets called. Is that the only thing that happens or is the entire object recreated then reassigned?
Last edited on
If you need a copy, do a copy.
If a copy makes things simpler, consider doing a copy.
If a copy is cheap, consider relaxing.
If your program is slow, look at the bottleneck.


> does "int b = a;" create a copy of the entire object and all it's members or just "22"?
¿what members do you think an int have?

> I guess it can slow things down
measure

> If I change the value of "a" to "3" (a = 3) the constructor gets called.
no.
what members do you think an int have?

I guess it have some safety functions etc that checks some things when created.


no.

When I create/ini a "self made" object then reassign it the constructor gets called.

E.g...
myobject obj(20);
obj = 66;


Last edited on
integers in c++ maybe you can think of them as a CPU hardware register, not a high level programming object. They are just raw bytes that sit in memory and represent a value. They have no methods. C++ adds a layer or two, like type safety (you will get a warning if you put a double into an int, because it drops the decimals, for example) but this is just a compiler AI/detection/warning algorithm, and has no effect on your code or run-time.

copying an int, then, is as efficient as it can be in the CPU/assembly instructions for your hardware, in c++. Its not like python, where you traverse a linked list to copy an integer.

this is why there are so many integer types. Its close to 100 if you count common platform names + language names + C inherited names and so on :P you have a name for signed 1,2,4,8 byte ints and unsigned 1,2,4,8 byte ints (and some systems now have 16 byte ints), and then a number of copies of these for historical reasons
Last edited on
myobject obj(20);
obj = 66;

First line is calling the constructor. Second line is calling the assignment operator.
Show compileable example if disagree.

And yes jonnin is completely correctly, copying an int is about as efficient as it can be.
Last edited on
First line is calling the constructor. Second line is calling the assignment operator.



If you are referring to: operator=() {..} , that gets called after the constructor when I included it.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
struct x1 {
	
	int z = 0;
	
	x1(int length){
		
		z = length;
	}

};




int main() {

	x1 x(20);
	x = 88;
	cout << x.z; //output: 88
	

	
}
Line 18: The constructor of the object x is not called. What happens is that an unnamed temporary variable of type x1 is created with the value 88 and assigned to x

If it creates a copy of the entire thing I guess it can slow things down if I have alot of copies instead of pointers/ref in my program?
You don't need to worry too much about copying a few hundreds or thousands bytes. This is usually not significant. Except you doing it a lot of times. Premature optimization is usually not a good thing to do.
Line 18: The constructor of the object x is not called. What happens is that an unnamed temporary variable of type x1 is created with the value 88 and assigned to x


That's strange, because when removing "z = length" inside the constructor the output of "x.z" is the initial value (0) instead of "88". That should mean that "88" goes through the constructor, when typing "x = 88".
That's strange, because when removing "z = length" inside the constructor the output of "x.z" is the initial value (0) instead of "88".
Sure, then there is no way that the 88 will be stored in z.

That should mean that "88" goes through the constructor, when typing "x = 88".
The constructor of the temporary variable is called. Once an object is constructed the constuctor will not be called anymore.

By the way: There is move and copy elision to optimize copying:

https://en.cppreference.com/w/cpp/utility/move
https://en.cppreference.com/w/cpp/language/copy_elision
Lets be verbose:
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
#include <iostream>

struct x1 {
	int z = 0;
	x1( int length ) : z{ length }
	{ std::cout << "ctor x1(int) " << z << '\n'; }
	x1( const x1& rhs ) : z{ rhs.z }
	{ std::cout << "copy ctor " << z << '\n'; }
	x1( x1&& rhs ) : z{ rhs.z }
	{ std::cout << "move ctor " << z << '\n'; }
	x1& operator= ( const x1& rhs )
	{ z = rhs.z; std::cout << "copy assign " << z << '\n';
	  return *this;
	}
	x1& operator= ( x1&& rhs )
	{ z = rhs.z; std::cout << "move assign " << z << '\n';
	  return *this;
	}
};

int main() {

	x1 x = 20;
	x = 88;
	std::cout << x.z << '\n';
}

ctor x1(int) 20
ctor x1(int) 88
move assign 88
88

Adding this to keskiverto program shows:
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
#include <iostream>

struct x1 {
	int z = 0;
	x1( int length ) : z{ length }
	{ std::cout << this << " ctor x1(int) " << z << '\n'; }
	x1( const x1& rhs ) : z{ rhs.z }
	{ std::cout << this << " copy ctor " << z << '\n'; }
	x1( x1&& rhs ) : z{ rhs.z }
	{ std::cout << this << " move ctor " << z << '\n'; }
	x1& operator= ( const x1& rhs )
	{ z = rhs.z; std::cout << this << " copy assign " << z << '\n';
	  return *this;
	}
	x1& operator= ( x1&& rhs )
	{ z = rhs.z; std::cout << this << " move assign " << z << '\n';
	  return *this;
	}
};

int main() {

	x1 x = 20;
	x = 88;
	std::cout << x.z << '\n';
}


0x7c13a73b4f50 ctor x1(int) 20 <----- x
0x7c13a73b4f60 ctor x1(int) 88 <------ temporary
0x7c13a73b4f50 move assign 88 <----- x
88
Last edited on
Topic archived. No new replies allowed.