Why is copy constructor called here? - c++

I have the following code:
template<class T = char>
class String
{
public:
// Default constructor
String()
: buffer(nullptr),
len(0)
{
cout << "Default constructor" << endl;
}
// Constructor
String(const char* s)
{
cout << "Constructor (const char*)" << endl;
//...
}
// Virtual destructor.
virtual ~String()
{
cout << "Destructor" << endl;
len = 0;
delete[] buffer;
}
// Copy constructor
String(const String& s)
{
cout << "Copy constructor" << endl;
buffer = new T[s.len];
std::copy(s.buffer, s.buffer + s.len, buffer);
len = s.len;
}
// Copy assignment operator (uses copy and swap idiom)
String& operator=(String s)
{
cout << "Copy assignment operator (copy and swap idiom)" << endl;
std::swap(buffer, s.buffer);
return *this;
}
// Move constructor
String(String&& s)
{
cout << "Move constructor" << endl;
}
// compound assignment (does not need to be a member,
// but often is, to modify the private members)
String& operator+=(const String& rhs)
{
cout << "operator+=" << endl;
//...
return *this; // return the result by reference
}
// friends defined inside class body are inline and are hidden from non-ADL lookup
// passing lhs by value helps optimize chained a + b + c
// otherwise, both parameters may be const references
friend String operator+(String lhs, const String& rhs)
{
cout << "operator+" << endl;
lhs += rhs; // reuse compound assignment
return lhs; // return the result by value (uses move constructor)
}
private:
T* buffer;
size_t len;
};
int main()
{
String<> s("Hello ");
String<> s2("World");
// call copy constructor first?
String<> s3 = s + s2;
return 0;
}
And the output is:
Constructor (const char*)
Constructor (const char*)
Copy constructor
operator+
operator+=
Move constructor
Destructor
My question is why is the copy constructor called immediately in:
String<> s3 = s + s2;

A value copy of s is taken by friend String operator+(String lhs, const String& rhs), essentially because s is not an anonymous temporary and is therefore not an appropriate candidate for move construction. Taking that value copy requires the copy constructor.

To my understanding, the copy constructor is called to receive the return value of the + operator.

Related

Class destructor is causing problem with overloading + operator

I can't figure out what is the problem with my C++ class (using Visual Studio). Visual Studio is not giving any desired output, just saying " exited with code -1073741819". I created a class named Complex using raw pointers, when no-args or parameterized constructor is called, memory is allocated using new int and when variable goes out of scope, destructor deallocates memory using delete keywords. The only problem i am facing is that, my + operator overloading causing problem and i am pretty sure that this problem is related to destructor, when i remove destructor code, + operator works just fine. Or when I don't use + operator, also then program works fine. Please help me by figuring out code. Please don't say to me that "you don't need raw pointers here", actually i have been told to do so (using only pointers). I am stuck on this for many hours.
Here is my code, please go through it , including + operator overloading code and destructor code.
#include<iostream>
using namespace std;
class Complex {
private:
int *real;
int *complex;
public:
// some declarations
Complex();
Complex(int, int);
Complex(const Complex& source);
Complex operator+ (const Complex& rhs);
Complex& operator= (const Complex& rhs);
void disp() {
cout << "(" << *real << "," << *complex << ")" << endl;
}
// destructor
~Complex() {
delete real;
real = nullptr;
delete complex;
complex = nullptr;
}
};
// no-args constructor
Complex::Complex() {
real = new int;
*real = 0;
complex = new int;
*complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {
*real = x;
*complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
// overloading + operator
Complex Complex::operator+ (const Complex &rhs) {
int a, b;
a = *(this->real) + *(rhs.real);
b = *(this->complex) + *(rhs.complex);
Complex temp(a,b);
return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
*(this->real) = *(rhs.real);
*(this->complex) = *(rhs.complex);
return *this;
}
int main() {
Complex n1(5,-9);
Complex n2(5,-1);
Complex n3;
n3=n1 + n2;
n3.disp();
return 0;
}
You don't allocate any memory in your copy constructor, so your assignments happen to uninitialized memory.
Complex::Complex(const Complex& source) {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
If I change it to this:
Complex::Complex(const Complex& source) : Complex() {
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
Your program outputs (10,-10)
EDIT: Question in the comments.
I have added a few printouts to your program to show exactly what is going on:
#include<iostream>
using namespace std;
class Complex {
private:
int* real;
int* complex;
public:
// some declarations
Complex();
Complex(int, int);
Complex(const Complex& source);
Complex operator+ (const Complex& rhs);
Complex& operator= (const Complex& rhs);
void disp() {
cout << "(" << *real << "," << *complex << ")" << endl;
}
// destructor
~Complex() {
std::cout << "destructor" << std::endl;
delete real;
real = nullptr;
delete complex;
complex = nullptr;
}
};
// no-args constructor
Complex::Complex() {
std::cout << "constructor" << std::endl;
real = new int;
*real = 0;
complex = new int;
*complex = 0;
}
// parameterized constructor
Complex::Complex(int x, int y) : Complex() {
std::cout << "(x,y)constructor" << std::endl;
*real = x;
*complex = y;
}
//copy constructor
Complex::Complex(const Complex& source) : Complex() {
std::cout << "copy constructor" << std::endl;
*(this->real) = *(source.real);
*(this->complex) = *(source.complex);
}
// overloading + operator
Complex Complex::operator+ (const Complex& rhs) {
std::cout << "op+" << std::endl;
int a, b;
a = *(this->real) + *(rhs.real);
b = *(this->complex) + *(rhs.complex);
Complex temp(a, b);
return temp;
}
// overloading = operator
Complex& Complex::operator= (const Complex& rhs) {
std::cout << "op=" << std::endl;
*(this->real) = *(rhs.real);
*(this->complex) = *(rhs.complex);
return *this;
}
int main() {
Complex n1(5, -9);
Complex n2(5, -1);
Complex n3;
n3 = n1 + n2;
n3.disp();
return 0;
}
Now running your program results this:
constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
constructor
copy constructor
destructor
op=
destructor
(10,-10)
destructor
destructor
destructor
As you can see, there is a "copy constructor" in there. Specifically this line: n3 = n1 + n2; results in this printout:
op+ // n1 + n2
constructor // base constructor from param constructor
(x,y)constructor // constructing the return value: Complex temp(a, b);
constructor // base constructor from copy constructor
copy constructor // copying from temp to the return value
destructor // destroying temp
op= // assigning the return value to n3
destructor // destroying the return value
Do note btw, that this was compiled in debug mode. If I compile in release mode the output changes:
constructor
(x,y)constructor
constructor
(x,y)constructor
constructor
op+
constructor
(x,y)constructor
op=
destructor
(10,-10)
destructor
destructor
destructor
The pertinent point here is that the compiler managed to optimize out the copy constructor, by recognizing that there is no point in constructing temp only to then copy and destroy it. But this only happens when optimization is turned on.
I'm suspecting that your parameterized constructor is the problem... In your parameterized constructor, you are creating a Complex class object, which takes the *real and *complex pointers, pointing it to the passed in integers(x and y). No memory is allocated hence when your program ends, your destructor gets called and attempts to deallocate memory inside n1 and n2 that were never dynamically allocated.
I haven't touched C++ in a few months, so I could be wrong. Feel free to check and get back to me on your results.

How can can I sort a vector of pointed-to values using std::sort()?

There is already the post sorting vector of pointers but this is not about a vector of pointers but rather about a vector of referencing pointers.
3 integer are put into a std::vector<int*> which is than sorted according to the values behind the pointers.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int a = 3;
int b = 2;
int c = 1;
std::vector<int*> vec;
vec.emplace_back(&a);
vec.emplace_back(&b);
vec.emplace_back(&c);
std::sort(vec.begin(), vec.end(), [](const int* a, const int* b) {
return *a < *b;
});
std::cout << "vec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n';
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
}
however, it seems that only the vector was sorted as the output shows:
vec = 1, 2, 3
abc = 3, 2, 1
I think the reason is that std::sort(), while comparing correctly, simply assigns adresses instead of the values. What is wrong here? Why can't I sort this vector of pointed-to values?
The next part is rather TL,DR as it shows my approach to solve this. An easy task that reveals itself to be rather frustratingly complicated. #Bathsheba's answer points out that it is not possible. So the next parts, initially considered to be the presentation of my attempt, might now be considered to be the reason why it is not possible.
My idea is to make a pointer class wrapper to provide my own contructors and assignement operators. std::sort() behaves differently if the size of the container is small (<= 32 on my system) but in both cases there are assignements and moves happening - as this small snippet from the _Insertion_sort_unchecked (from <algorithm>) function shows.
(_BidIt == std::vector<int*>::iterator and _Iter_value_t<_BidIt> == int*)
_BidIt _Insertion_sort_unchecked(_BidIt _First, const _BidIt _Last, _Pr _Pred)
{ // insertion sort [_First, _Last), using _Pred
if (_First != _Last)
{
for (_BidIt _Next = _First; ++_Next != _Last; )
{ // order next element
_BidIt _Next1 = _Next;
_Iter_value_t<_BidIt> _Val = _STD move(*_Next);
if (_DEBUG_LT_PRED(_Pred, _Val, *_First))
{ // found new earliest element, move to front
_Move_backward_unchecked(_First, _Next, ++_Next1);
*_First = _STD move(_Val);
Let's make a class assignement_pointer that behaves like a pointer except that it assigns the values instead of the adresses.
template<typename T>
class assignement_pointer {
public:
assignement_pointer(T& value) {
this->m_ptr = &value;
std::cout << "<T>& constructor\n";
}
assignement_pointer(const assignement_pointer& other) {
this->m_ptr = other.m_ptr;
std::cout << "copy constructor\n";
}
assignement_pointer(assignement_pointer&& other) {
std::cout << "move assignement constructor >> into >> ";
*this = std::move(other);
}
assignement_pointer& operator=(const assignement_pointer& other) {
*this->m_ptr = *other.m_ptr;
std::cout << "copy assignement operator\n";
return *this;
}
assignement_pointer& operator=(assignement_pointer&& other) {
std::swap(this->m_ptr, other.m_ptr);
std::cout << "move assignement operator\n";
return *this;
}
T& operator*() {
return *this->m_ptr;
}
const T& operator*() const {
return *this->m_ptr;
}
private:
T* m_ptr;
};
As you can see there are also temporary std::cout's to see which constructors / assignement operators were called while going through std::sort() in the main:
///...
std::vector<assignement_pointer<int>> vec;
vec.reserve(3);
vec.emplace_back(assignement_pointer(a));
vec.emplace_back(assignement_pointer(b));
vec.emplace_back(assignement_pointer(c));
std::cout << "\nsort()\n";
std::sort(vec.begin(), vec.end(), [](const assignement_pointer<int>& a, const assignement_pointer<int>& b) {
return *a < *b;
});
std::cout << "\nvec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n';
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
giving the output:
<T>& constructor
move assignement constructor >> into >> move assignement operator
<T>& constructor
move assignement constructor >> into >> move assignement operator
<T>& constructor
move assignement constructor >> into >> move assignement operator
sort()
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
move assignement operator
vec = 1, 2, 3
abc = 3, 2, 1
std::sort() calls only move functions.
again, vec is sorted but not a, b, c
the last point makes sense, because since only move functions are called the copy assignement operator assignement_pointer& operator=(const assignement_pointer& other); (which does the value assignement) is never called. The unnecessary copy constructor and assignement operator can be removed:
template<typename T>
class assignement_pointer {
public:
assignement_pointer(T& value) {
this->m_ptr = &value;
}
assignement_pointer(const assignement_pointer& other) = delete;
assignement_pointer& operator=(const assignement_pointer& other) = delete;
assignement_pointer(assignement_pointer&& other) {
std::cout << "move assignement constructor >> into >> ";
*this = std::move(other);
}
assignement_pointer& operator=(assignement_pointer&& other) {
std::swap(this->m_ptr, other.m_ptr);
std::cout << "move assignement operator\n";
return *this;
}
T& operator*() {
return *this->m_ptr;
}
const T& operator*() const {
return *this->m_ptr;
}
private:
T* m_ptr;
};
Now std::sort() inner processes are rather complicated but in the end it comes down to failing at an operation like std::swap():
int main() {
int a = 3;
int b = 2;
std::vector<assignement_pointer<int>> vec;
vec.reserve(2); //to avoid re-allocations
vec.emplace_back(assignement_pointer(a));
vec.emplace_back(assignement_pointer(b));
std::cout << "swap()\n";
assignement_pointer<int> ptr_a{ a };
assignement_pointer<int> ptr_b{ b };
std::swap(ptr_a, ptr_b);
std::cout << "\nptrs = " << *ptr_a << ", " << *ptr_b << '\n';
std::cout << "a, b = " << a << ", " << b << '\n';
}
and as this output shows:
move assignement constructor >> into >> move assignement operator
move assignement constructor >> into >> move assignement operator
swap()
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
ptrs = 2, 3
a, b = 3, 2
it's that sitation that only the pointers are switched but not the original variables. std::swap is basically
_Ty _Tmp = _STD move(_Left);
_Left = _STD move(_Right);
_Right = _STD move(_Tmp);
explaining the
move assignement constructor >> into >> move assignement operator
move assignement operator
move assignement operator
the move assignement operator simply swaps the pointers so creating a temporary variable doesn't do anything.
I see two possible solutions to this:
make the move assignement operator not swap pointers but rather values.
implement my own swap() for the class
but both don't work.
the move assignement operator can't swap values because the initial m_ptr from this-> class is always nullptr and I would rather not dereference this.
std::sort() never uses std::swap() but instead just std::move()s from all over the place. (as already partially seen by _Insertion_sort_unchecked).
You'll need to roll your own sort function to do this.
The callback lambda is used to evaluate the ordering, but you need to tweak the part that does the actual exchange of elements: and the C++ standard library sort does not support your doing that.
Fortunately a quick sort without any bells and whistles (such as pre-randomisation) comes out in a few tens of lines, so this is not a particularly onerous task to complete.
Just retain a copy of the original vector of pointers and copy the sorted values over:
std::vector<int*> original = vec; // Do this before the std::sort
Then after you print a,b,c:
std::vector<int> xfer;
for (auto ptr : vec) {
xfer.push_back(*ptr);
}
auto it = std::begin(xfer);
for (auto ptr : original) {
*ptr = *it++;
}
std::cout << "abc = " << a << ", " << b << ", " << c << '\n';
Output:
abc = 1, 2, 3

why isn't my copy constructor called when I do a copy and swap idiom?

In the following code, when assignment operator is used, why is the copy constructor not being called or why is there no print corresponding to it?
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
class Person {
private:
char* name;
int age;
public:
Person() {
name = nullptr;
age = 10;
}
Person(const char* p_name, int p_age) {
name = new char[strlen(p_name) + 1];
strcpy(name, p_name);
age = p_age;
}
Person(Person const& p) {
cout << "Person copy constructor with " << p.name << endl;
name = new char[strlen(p.name) + 1];
strcpy(name, p.name);
age = p.age;
}
/*self assignment
The first is the self-assignment test. This check serves two purposes: it's an easy way to prevent us from running needless code on self-assignment,
and it protects us from subtle bugs (such as deleting the array only to try and copy it).
But in all other cases it merely serves to slow the program down, and act as noise in the code; self-assignment rarely occurs, so most of the time
this check is a waste. It would be better if the operator could work properly without it.*/
/*
Person& operator=(Person const& p) {
cout << "Person copy assignment with " << p.name << endl;
if(this != &p){
delete[] name;
name = nullptr;
name = new char[strlen(p.name) + 1];
strcpy(name, p.name);
age = p.age;
}
return *this;
}
*/
/*exception safety
If in the previous approach the memory allocation fails and throws an exception then the data in name is gone*/
/*
Person& operator=(Person const& p) {
cout << "Person copy assignment with " << p.name << endl;
char* temp_name = new char[strlen(p.name) + 1];
strcpy(temp_name, p.name);
delete[] name;
name = temp_name;
age = p.age;
return *this;
}
*/
//copy and swap idiom
/*
. Not only that, but this choice is critical in C++11, which is discussed later.
(On a general note, a remarkably useful guideline is as follows: if you're going to make a copy of something in a function,
let the compiler do it in the parameter list.‡)
*/
Person& operator=(Person p) {
cout << "Person copy assignment with " << p.name << endl;
swap(*this, p);
return *this;
}
/*
A swap function is a non-throwing function that swaps two objects of a class, member for member. We might be tempted to
use std::swap instead of providing our own, but this would be impossible; std::swap uses the copy-constructor and
copy-assignment operator within its implementation, and we'd ultimately be trying to define the assignment operator in terms of itself!
*/
friend void swap(Person &a, Person &b) {
using std::swap;
swap(a.name, b.name);
swap(a.age, b.age);
}
Person(Person&& other) {
swap(*this, other);
}
~Person() {
if(name)
cout << "Person destructor called for " << name << endl;
delete[] name;
}
};
int main() {
Person p("Ryan", 28);
Person a(p);
a = p;
cout << "Hello World" << endl;
return 0;
}
The output of the above code is:
Person copy constructor with Ryan
Person copy constructor with Ryan
Person copy assignment with Ryan
Person destructor called for Ryan
Hello World
Person destructor called for Ryan
Person destructor called for Ryan
why is the copy constructor not being called/there is no print corresponding to it.
Actually it's being called just fine. You can see right here in your own output:
Person copy constructor with Ryan
Person copy constructor with Ryan <--- This is it : )
Person copy assignment with Ryan
See here is the call site:
a = p;
and this is your assignment operator:
Person& operator=(Person p) {
cout << "Person copy assignment with " << p.name << endl;
swap(*this, p);
return *this;
}
So the copy constructor is being called here for who? and when? It's being called for this parameter p (with the RHS of the = from the call site as its parameter) right before entering the body of your operator= code. Hence in the output you see it as the line adjacently preceding this one:
Person copy assignment with Ryan

Understanding C++ copy constructor behavior

This is my code:
#include <iostream>
using namespace std;
class A
{
int i;
public:
A(int v) : i(v) { }
A(const A& r) : i(r.i) {
cout << "Copy constructor" << endl;
}
A operator=(const A& r) {
cout << "Assignment function" << endl;
return r;
}
void show() {
cout << i << endl;
}
};
int main()
{
A a(1);
A b(2);
a = b;
a.show();
return 0;
}
Value of b is 2 and value of a is 1. In 'main', b is copied into a and this the output I get:
Assignment function
Copy constructor
This is understandable, but the output for a.show() comes out be 1. I can't understand this. How? Because b is copied into a using the copy constructor so shouldn't a.i have the value of b.i?
b is copied into a using the assignment operator, not the copy constructor. And your assignment operator doesn't assign i, so a.i keeps its original value.
The copy constructor you are seeing is for the return value of operator=. It is more customary to return the left-hand-side by reference, not the right-hand-side by value:
A& operator=(const A& r) {
cout << "Assignment function" << endl;
i = r.i;
return *this;
}
When you define the assignment operator you have to do all of the work to copy the data.
A operator=(const A& r) {
cout << "Assignment function" << endl;
i = r.i;
return r;
}
so a = b is calling your assignment operator (obviously, hence your output). But right now it isn't copying anything.
The assignment operator doesn't do anything to the "assigned to" object. The copy constructor call you see reported is from the creation of the assignment return value.
Your copy assignment should probably look loke this:
A& A::operator= (A const& other) {
// output
this->i = other.i;
return *this;
}

Does it make sense to make the copy constructor explicit in C++? [duplicate]

I have extended std::string to fulfil my needs of having to write custom function build into string class called CustomString
I have defined constructors:
class CustomString : public std::string {
public:
explicit CustomString(void);
explicit CustomString(const std::string& str);
explicit CustomString(const CustomString& customString);
//assignment operator
CustomString& operator=(const CustomString& customString);
... };
In the third constructor (copy constructor) and assignment operator, whose definition is:
CustomString::CustomString(const CustomString& customString):
std::string(static_cast<std::string>(customString))
{}
CustomString& CustomString::operator=(const CustomString& customString){
this->assign(static_cast<std::string>(customString));
return *this;
}
First since this is an "explicit"; meaning an explicit cast is needed to assign to another CustomString object; it's complaining about the assignment.
CustomString s = CustomString("test");
I am not sure where exactly is casting needed explicitly.
The code works alright if copy constructor is not explicit but I would like to know and implement explicit definition instead of "guessing proper cast".
The explicit copy constructor means that the copy constructor will not be called implicitly, which is what happens in the expression:
CustomString s = CustomString("test");
This expression literally means: create a temporary CustomString using the constructor that takes a const char*. Implicitly call the copy constructor of CustomString to copy from that temporary into s.
Now, if the code was correct (i.e. if the copy constructor was not explicit), the compiler would avoid the creation of the temporary and elide the copy by constructing s directly with the string literal. But the compiler must still check that the construction can be done and fails there.
You can call the copy constructor explicitly:
CustomString s( CustomString("test") );
But I would recommend that you avoid the temporary altogether and just create s with the const char*:
CustomString s( "test" );
Which is what the compiler would do anyway...
Deriving from std::string is not safe, as std::string has no virtual destructor. As to your question - your copy constructors should not be explicit, to allow for such usage as:
CustomString s = "test";
Also I have no idea why you would want to declare a copy-constructor as explicit, as it is not needed.
An explicit copy-constructor will work only if you declare your CustomString object as:
CustomString s(CustomString("test"));
It seems current gcc won't invoke the copy constructor tested in gcc 8.2(MinGW.org GCC-8.2.0-5),and will utilize to call constructor directly For X1
#include <iostream>
using std::cout;
using std::endl;
class X1 {
public:
X1() {
cout<< "invoke constructor" << endl;
};
explicit X1(const X1 &obj) {
cout << "invoke copy constructor" << endl;
};
X1(X1&& obj) {
cout << "invoke move constructor" << endl;
};
X1& operator=(const X1 &obj) {
cout << "invoke value assign constructor " << endl;
if(this == &obj) {
return *this;
}
return *this;
};
X1& operator=(const X1 && obj) {
cout << "invoke move value assign constructor " << endl;
if(this == &obj) {
return *this;
}
return *this;
};
~X1() {
cout << "invoke deconstruct" << endl;
};
};
int main() {
// X1 l1(1);
// X1 l3(2);
X1 l4 = X1();
return 0;
}