Copy Constructor, Assignment Operator¶
Compiler Generated Copy Constructor¶
Rule
Copy constructor and copy assignment operator are automatically generated if …
there is no user defined move constructor
there is no user defined move assignment operator
The venerable class point
from Classes and Objects is simple
Contains only data members
Has no user-defined copy constructor ⟶ compiler-generated
Does not do resource management in whatever way (see here for why this is dangerous)
⟶ letting the compiler its way is fine
Copy constructor in action (no matter if it is generated or hand-written) …
#include <gtest/gtest.h>
#include "point.h"
TEST(cpp_copy_suite, generated_copy_ctor)
{
point original{1,2};
point copy1 = original; // <--- assignment style, but ctor
point copy2(original); // <--- c++03 style
point copy3{original}; // <--- c++11 style
ASSERT_EQ(copy1.x(), 1);
ASSERT_EQ(copy1.y(), 2);
ASSERT_EQ(copy2.x(), 1);
ASSERT_EQ(copy2.y(), 2);
ASSERT_EQ(copy3.x(), 1);
ASSERT_EQ(copy3.y(), 2);
}
Manually Written Copy Constructor And Assignment Operator¶
Caution
Careful: if you find yourself writing a copy constructor …
You should be writing an assignment operator just as well
You should probably implement move semantics just as well
You should probably implement a destructor just as well
You should probably be careful, and read Object Copy (And Resource Management): There Be Dragons
⟶ Rule of 5/0
For demonstration purposes: a completely nonsensical copy constructor and assignment operator:
#include <gtest/gtest.h>
#include <string>
class Copyable
{
public:
Copyable() = default; // <--- not auto-generated because other ctors are user defined
Copyable(const std::string& content)
: content(content) {}
Copyable(const Copyable& other) // <--- copy constructor
: content(other.content + " (copy)") {}
Copyable& operator=(const Copyable& other) // <--- assignment operator
{
content = other.content + " (assignment)";
return *this;
}
std::string content;
};
TEST(manual_copy_suite, copy_ctor)
{
Copyable original("some object");
Copyable copy = original; // <--- copy constructor
ASSERT_EQ(original.content, "some object");
ASSERT_EQ(copy.content, "some object (copy)");
}
TEST(manual_copy_suite, assignment_operator)
{
Copyable original("some object");
Copyable copy;
copy = original; // <--- assignment operator
ASSERT_EQ(original.content, "some object");
ASSERT_EQ(copy.content, "some object (assignment)");
}