Why is this code trying to call the copy constructor?
If you are using Visual Studio 2010 or 2012, be advised: the compiler does not automatically generate move constructors for you. That wasn't implemented. So you need to write them yourself.
C++ Why was the copy constructor called?
B(A aa)
takes an A
by value, so when you execute B b(a)
the compiler calls the copy constructor A(const A& a)
to generate the instance of A
named aa
in the explicit
constructor for B
.
The reason you can remove the copy constructor and have this still work is that the compiler will generate a copy constructor for you in cases where you have not also declared a move constructor.
Note: The compiler generated copy constructor is often not sufficient for complex classes, it performs a simple member wise copy, so for complex elements or dynamically allocated memory you should declare your own.
§ 15.8.1
If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly.
If the class definition declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is defined as defaulted (11.4). The latter case is deprecated if
the class has a user-declared copy assignment operator or a user-declared destructor or assignment operator.
Why is the copy constructor called in this code after the assignment operator?
Because if you don't return a reference of the object it makes a copy.
As @M.M said about the final test() call, the copy does not appears because of the copy elision What are copy elision and return value optimization?
Why does my operator + overload call my copy constructor despite being passed by reference?
Creating a temporary point and changing its values will not call the copy constructor.
You are returning an object here, not a pointer or a reference to an object:
point operator + (const point& A, const point& B) { //Adds x1 to x2, y1 to y2
when you return from your function a new object is created from the one that you had inside your function and this is where the copy constructor gets called.
Why does calling std::move on a const object call the copy constructor when passed to another object?
The type of the result of calling std::move
with a T const
argument is T const&&
, which cannot bind to a T&&
parameter. The next best match is your copy constructor, which is deleted, hence the error.
Explicitly delete
ing a function doesn't mean it is not available for overload resolution, but that if it is indeed the most viable candidate selected by overload resolution, then it's a compiler error.
The result makes sense because a move construction is an operation that steals resources from the source object, thus mutating it, so you shouldn't be able to do that to a const
object simply by calling std::move
.
c++ constructor and copy constructor
What you are seeing is called copy elision in a pre-C++17 compiler (try it out with C++17 on compiler explorer or wandbox with -std=c++17
vs. -std=c++14
flags). As of C++17 the compiler is required to eliminate many cases of copy and move constructors, and construct objects directly without any intermediate objects.
Unlike
A a { 10 };
the line
A a = 10;
means that a temporary object is constructed first, as if the code has:
A a = A(10);
Until C++17, the compiler was allowed to optimize this code, and construct a
directly from 10
without the temporary object. Note that the emphasis is that it was allowed but not required to do this copy elision optimization. You have observed this allowed optimization.
The compiler had to compile or fail the code regardless of its decision to do copy elision. If the compiler could not call the copy constructor, like in your case, then it had to fail the compilation unconditionally, even if it decided to do copy elision. This changed with C++17, and the compiler is now required to make the copy elision optimization in this case. Since it is guaranteed to elide the copy constructor, no copy constructor is even required and the code can compile without an error.
Note the copy constructor without const:
A(A &other) { std::cout << " other " << std::endl; value = other.value; }
Without copy elision, this copy constructor can't be used for:
A a = A(10);
It can't be used because A(10) is a temporary object, and as such can be passed as an rvalue parameter to constructors and methods like
A(A && other);
foo(A && other);
or passed as a const lvalue reference parameter to constructors and methods like
A(const A& other);
bar(const A& other);
But it can't be passed as a regular mutable parameter (like in your code block 3).
With copy elision it does not even try to call the copy or the move constructor in these cases.
It still needs to call the copy constructor for
A b = a;
and it can do that with a mutable parameter, only because a
is neither a temporary nor a const object. If you make a
const then the code will fail to compile, when the copy constructor does not get a const (for C++17 and earlier):
const A a = 10;
A b = a;
// ^^ this will fail
Fun note: The following line will is guaranteed not to call the copy constructor even once with C++17:
A a = A(A(A(A(1))));
why isn't the copy constructor called
This is called as copy elision.
The compilers are allowed to do this optimization. Though it is not guaranteed by the standard any commercial compiler will perform this optimization whenever it can.
Standard Reference:
C++03 12.8.15:
[...] This elision of copy operations is
permitted in the following
circumstances (which may be combined
to eliminate multiple copies):[...]
- when a temporary class object that has
not been bound to a reference (12.2)
would be copied to a class object with
the same cv-unqualified type, the copy
operation can be omitted by
constructing the temporary object
directly into the target of the
omitted copy
You might use some compiler settings to disable this optimization, like in case of gcc, from the man page:
-fno-elide-constructor
The C++ standard allows an implementation to omit creating a temporary which is only used to initialize another object of the same type. Specifying this option disables that optimization, and
forces G++ to call the copy constructor in all cases.
However, using this makes your code non portable across different compilers.
What is referencing the copy constructor?
It's not just about the unnecessary copy and C++17, we know that
Logger::Log foo("sample.log");
works fine but why this flags C2280 Error
Logger::Log foo = Logger::Log::Log("sample.log");
the problem is in ofstream that is in the class, I got your code and I compiled it, I had a doubt about ofstream object, I deleted it, and it works fine also I made it a pointer also works fine, then I tried this code:
std::ofstream s = std::ofstream("sample.log", std::ios::out);
std::ofstream k;
k = s;
I got this error E1776 function "std::basic_ofstream<_Elem, _Traits>::operator=(const std::basic_ofstream<_Elem, _Traits> &) [with _Elem=char, _Traits=std::char_traits]" (declared at line 1080 of "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.25.28610\include\fstream") cannot be referenced -- it is a deleted function
which means ofstream prevent copy constructor and =operator to avoid the access to the same data (file) and this is the case in your code, when you call the copy constructor by this line
Logger::Log foo = Logger::Log::Log("sample.log");
implicitly using the default copy constructor, it copies field by field using =operator for each object you have or a primitive type, and this is the case with ofstream that prevents the =operator then the compiler flags with calling a deleted function error--
to solve this you can declare ofstream pointer using raw pointers or smart ones and manage the memory or you can also create your move constructor version with your customization --which will delete the default copy constructor in your class also-- and try to avoid the access to the same data using different ofstreams.
Related Topics
Does Std::Vector *Have* to Move Objects When Growing Capacity? Or, Can Allocators "Reallocate"
How to Detect Existence of a Class Using Sfinae
Function Overloading Based on Value VS. Const Reference
Construct Path for #Include Directive with MACro
C++ Qt Signal and Slot Not Firing
C++ HTML Template Framework, Templatizing Library, HTML Generator Library
How Does the Standard Library Implement Std::Swap
What Happens to Global Variables Declared in a Dll
How Are C++ Array Members Handled in Copy Control Functions
Std::Strings's Capacity(), Reserve() & Resize() Functions
Warning: Format Not a String Literal and No Format Arguments
What Kinds of Optimizations Does 'Volatile' Prevent in C++
Tell Cin to Stop Reading at Newline
Constant References with Typedef and Templates in C++
List of Standard Header Files in C and C++
Is There a Good Python Library That Can Parse C++
Narrowing Conversions in C++0X. Is It Just Me, or Does This Sound Like a Breaking Change