I looked through different thread and I have a hard time understanding how to utilize copy constructor.
If I want to manipulate my class, but I need to have original values to do so, I have to create a copy.
class object {
public:
int member[5][5];
object(object&); <-- how do we create a copy here?
void manipulate() {
<<-- how do I call it here?
}
};
I've been trying different things such as object copy = object(object&) but it does not work.
object(object&); <-- how do we create a copy here?
One simple way is to omit the declaration, and let C++ compiler do it for you. Since your object does not allocate resources in its constructor's body, C++ can handle creating the copy constructor for you.
<<-- how do I call it here?
Like this:
object copy(*this);
... // Manipulate it here
object( const object &obj )
{
for ( size_t i = 0; i < 5; i++ )
{
for ( int j = 0; j < 5; j++ )
{
member[i][j] = rhs.member[i][j];
}
}
}
Or you can write simply
object( const object &obj ) = default;
because your copy constructor does not do something special.
As for its using then you may use it the following way
object one;
onject two( one );
or
object one;
onject two = one;
or even as
object one;
onject two { one };
or
object one;
onject two = { one };
Also take into account that if you explicitly defined the copy constructor then you should explicitly define the default constructor if you need to have it.
A copy constructor is usually created because you cannot use the one generated by the compiler. In such a case, you will usually copy each member one by one.
For example (written on the fly - not sure if it would even compile with errors/warnings)
class A
{
public:
A();
A(const A& src)
{
m_array = (char*)new char[src.m_arraySize];
memcpy(m_array, src.m_array, src.m_arraySize);
m_arraySize = src.m_arraySize;
}
private:
char* m_array;
int m_arraySize;
};
Related
Could anyone explain me the reason why is in this code defined MyClass ( const MyClass & src ) { m_X = src . m_X; } ? Without this line of code it works fine as well and gives the same output which is 32 in this case. What's the difference between having it in and not? I read that copy constructor is made automatically but when you have defined pointer in the class you should define it but i don't get why in this case.
Code below:
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass ( int x ) : m_X ( new int ( x ) ) {}
MyClass ( const MyClass &src )
{
m_X = src.m_X;
}
void print ( void ) const
{
cout << *m_X;
}
private:
int * m_X;
};
int main ( void )
{
MyClass a ( 32 ), c = a;
c.print ();
return 0;
}
The default copy constructor as well as your copy constructor does a member wise copy (or shallow copy). In this case you have a pointer which value is the address of where the data is located. This address what is copied.
As noted in other posts you will need to manage pointers a little better.
The problem with the compiler generted one (and yours) is that it copies the pointer. You now have two pointers c.m_x and a.m_x both pointing at the same heap allocated object. Who owns it? What happens if you delete a, it should delete the memory it allocated (you incorrectly dont do this) , but c is still poining at it.
For this reason there is std::shared_ptr. It is designed for this case, it does the Right Thing By Magic
Replace int * m_X by std::shared_ptr<int> m_X
The reason you get the same output is you are doing a shallow copy just like the compiler would do. It is not enough just to copy a pointer. You need to create a new pointer and then set its value to be a copy of what you are copying from. A proper constructor would look like
MyClass ( const MyClass & src ) : m_X(new int(*src.m_X) {}
Now the copy has its own independent pointer that has the same value.
Also note that you need a destructor to delete the memory and a proper copy assignment operator as the default copy assignment operator will do the same thing as the default copy constructor.
In my main, I am calling a function (func1)in a loop. This function is a member of Class1. I am passing an object (object2) of a different class, Class2 to this function. On the first iteration of the loop, the variable var2 (member of Class2) is accessible from main, but on the second iteration, it is not. I get an "Access violation reading location" error. Here is what my code looks like:
main.cpp:
#include "Class1.h"
int main(){
Class2 object2;
object2.assign_var2();
Class1 object1;
for (int i = 0; i < 2; ++i){
std::cout << object2.var[0][0][0] << std::endl; // Works ONLY on first iteration
object1.func1(object2)
}
}
Class2.h:
class Class2{
... other variables and functions declared
public:
Class2::Class2();
Class2::~Class2();
double *** var2;
void assign_var2();
}
Class2.cpp:
Class2::Class2(){
var2 = new double**[200];
for (int i = 0; i < 200; ++i) {
var2[i] = new double*[200];
for (int j = 0; j < 200; ++j){
var2[i][j] = new double[2];
}
}
Class2::~Class2(){
for (int i = 0; i < 200; ++i){
for (int j = 0; j < 200; ++j){
delete [] var2[i][j];
}
delete [] var2[i];
}
delete [] var2;
}
void assign_var2(){
for (int i = 0; i<200; ++i){
for (int j = 0; j<200; ++j){
var2[i][j][0] = some_number1;
var2[i][j][1] = some_number2;
}
}
}
}
Class1.h:
#include "Class2.h"
class Class1{
... other variables, functions declared
public:
void func1(Class2)
}
Class1.cpp:
Class1::func1(Class2 object2){
int u = object2.var2[1][2][0];
int v = object2.var2[1][2][1];
}
Side note: If I try and print a different variable instead of var2, it seems to work on the second iteration, so I don't think it's a problem with the object itself.
Thanks in advance!!
The problem is that Class1::func1(Class2 object2) accepts the argument by value. This means that a copy of the Class2 object is being made, and then destructed when func1() returns.
In the Class2 class you do not define a copy constructor, so the compiler is creating one for you that simply copies the members by-value. Then when the copy's destructor runs, it deletes all of the allocations, leaving the original object with a pointer to an invalid object. This is why it fails on the second iteration.
Always follow the rule of three: if you need a custom destructor, copy constructor, or copy assignment operator, you need all three of them. A proper copy constructor will create new allocations for all of the arrays and copy the data to them. (If you are using C++11 then it's actually the rule of five: you probably also want to implement a move constructor and move assignment operator so that you can "steal" the var2 pointer in cases where you know that the object being assigned is an rvalue and therefore will be going away soon anyway.)
In your case, the fix is simple: accept the argument by value:
Class1::func1(Class2 const & object2)
I would strongly suggest using std::vector<std::vector<std::vector<double>>> for your var2 member instead, because then the compiler-generated destructor, copy-constructor, and copy-assignment operator will all do the right thing, and you won't need to implement any of them.
This works hand-in-hand with making func1() accept a reference: while the error is happening because there isn't a custom copy constructor, we really don't even want to make a copy here because we're not modifying the data. Copying the data only to destroy the copy is silly; let's just accept a reference to an existing object instead of requiring a superfluous copy.
Alternatively, you can just disable copying altogether:
class Class2 {
// ...
// For C++11: explicitly delete the copy-ctor and copy-assignment operator.
public:
Class2(Class2 const &) = delete;
Class2 & operator=(Class2 const &) = delete;
// For C++03: declare the copy-ctor and copy-assignment operator private and
// then do not implement them. (C++03 doesn't have the "= delete" syntax.)
private:
Class2(Class2 const &);
Class2 & operator=(Class2 const &);
If you disable copying then you would get a compile-time error on the call object1.func1(object2) because it depends on the existence of a copy-constructor for object2.
I create a class type Test and constructor with parameter, however, when I want to assign the constructor I create to a new constructor through the function f, the program crashes! Did anybody know why!?
The code:
class Test
{
public:
int number;
int *a;
Test(int n){
a = new int[n];
}
~Test(){
delete []a;
}
};
Test f(Test Ft1)
{
// Do something.
return Ft1;
}
int main()
{
Test t1(3);
t1.number = 5;
Test t2 = f(t1);
return 0;
}
The problem is that you are deleting twice the same array a when t1 and t2 destructors are called:
t1 and t2 have their member variable a pointing to the same memory location. When you do Test t2 = f(t1), a copy of t1 is created and is assigned to t2. You did not define a specific copy constructor, so the compiler defined it implicitly for you. However it simply copies the value of a (and does not do a new allocation as you might expect).
As best practice, I would recommend to add your own:
- copy constructor
- copy assignment
(cf rule of three)
Concerning the variable member a design:
- If you want t1 and t2 to point to the same array, then you can use shared_ptr
- If you want t1 and t2 to have their own array, then it would be simpler to use a vector<int> for a
Edit: in case you need to use a raw pointer, here is a quick example of how you can manage the memory in copy constructor and operator assignment. May I recommend you to read a reference book about it (for instance Effective C++ , chapter 11)? It will explain you the key concepts and the pitfalls.
class Test{
public:
int number;
int *a;
Test(int n){
a = new int[n];
}
~Test(){
delete [] a;
}
Test(const Test& that)
{
int size = sizeof(that.a);
a = new int[size];
memcpy (a, that.a, sizeof(size));
}
Test& operator=(const Test& that)
{
if (this != &that)
{
delete [] a;
int size = sizeof(that.a);
a = new int[size];
memcpy (a, that.a, sizeof(size));
}
return *this;
}
};
Test f(Test Ft1){
//do something
return Ft1;
}
int main(){
Test t1(3);
t1.number = 5;
Test t2 = f(t1);
// Test t3(t1); // calls copy constructor
// t3 = t1; // calls assignment operator
return 0;
}
The cause of your problem is that there is a thing called "binary copy". When special assignment/copy constructors are not defined, this binary copy kicks in. When one of your object gets copied over another, 2 different instances start own the same array because the pointer gets overwritten and the original array from the destination object gets leaked.
Compiler thinks that it is ok to copy contents of one object to another with a simple memcpy() (the picture is slightly more simplified but in essence what I write is correct). This is a constant source of problems, but this is how the language is defined. There is no way to do it any other way today. Tons of code are written and these tons expect exactly this.
First you need to decide what should happen with this array after copying. Should both objects co-own the array of the source object, should this array be duplicated at this point or anything else. Once you decide this, you need to implement this strategy in the assignment/copy constructors.
I've been exploring the possibilities of Move Constructors in C++, and I was wondering what are some ways of taking advantage of this feature in an example such as below. Consider this code:
template<unsigned int N>
class Foo {
public:
Foo() {
for (int i = 0; i < N; ++i) _nums[i] = 0;
}
Foo(const Foo<N>& other) {
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other) {
// ??? How can we take advantage of move constructors here?
}
// ... other methods and members
virtual ~Foo() { /* no action required */ }
private:
int _nums[N];
};
Foo<5> bar() {
Foo<5> result;
// Do stuff with 'result'
return result;
}
int main() {
Foo<5> foo(bar());
// ...
return 0;
}
In this above example, if we trace the program (with MSVC++ 2011), we see that Foo<N>::Foo(Foo<N>&&) is called when constructing foo, which is the desired behaviour. However, if we didn't have Foo<N>::Foo(Foo<N>&&), Foo<N>::Foo(const Foo<N>&) would be called instead, which would do a redundant copy operation.
My question is, as noted in the code, with this specific example which is using a statically-allocated simple array, is there any way to utilize the move constructor to avoid this redundant copy?
First off, there's a general sort of advice that says you shouldn't write any copy/move constructor, assignment operator or destructor at all if you can help it, and rather compose your class of high-quality components which in turn provide these, allowing the default-generated functions to Do The Right Thing. (The reverse implication is that if you do have to write any one of those, you probably have to write all of them.)
So the question boils down to "which single-responsibility component class can take advantage of move semantics?" The general answer is: Anything that manages a resource. The point is that the move constructor/assigner will just reseat the resource to the new object and invalidate the old one, thus avoiding the (presumed expensive or impossible) new allocation and deep copying of the resource.
The prime example is anything that manages dynamic memory, where the move operation simply copies the pointer and sets the old object's pointer to zero (so the old object's destructor does nothing). Here's a naive example:
class MySpace
{
void * addr;
std::size_t len;
public:
explicit MySpace(std::size_t n) : addr(::operator new(n)), len(n) { }
~MySpace() { ::operator delete(addr); }
MySpace(const MySpace & rhs) : addr(::operator new(rhs.len)), len(rhs.len)
{ /* copy memory */ }
MySpace(MySpace && rhs) : addr(rhs.addr), len(rhs.len)
{ rhs.len = 0; rhs.addr = 0; }
// ditto for assignment
};
The key is that any copy/move constructor will do a full copying of the member variables; it is only when those variables are themselves handles or pointers to resources that you can avoid copying the resource, because of the agreement that a moved object is no longer considered valid and that you're free to steal from it. If there's nothing to steal, then there's no benefit in moving.
In this case it's not useful because int has no move-constructors.
However, it could be useful if those were strings instead, for example:
template<unsigned int N>
class Foo {
public:
// [snip]
Foo(Foo<N>&& other) {
// move each element from other._nums to _nums
std::move(std::begin(other._nums), std::end(other._nums), &_nums[0]);
}
// [snip]
private:
std::string _nums[N];
};
Now you avoid copying strings where a move will do. I'm not sure if a conforming C++11 compiler will generate equivalent code if you omit all the copy-/move-constructors completely, sorry.
(In other words, I'm not sure if std::move is specially defined to do an element-wise move for arrays.)
For the class template you wrote, there's no advantage to take in a move constructor.
There would be an advantage if the member array was allocated dynamically. But with a plain array as a member, there's nothing to optimize, you can only copy the values. There's no way to move them.
Usually, move-semantic is implemented when your class manages resource. Since in your case, the class doesn't manages resource, the move-semantic would be more like copy-semantic, as there is nothing to be moved.
To better understand when move-semantic becomes necessary, consider making _nums a pointer, instead of an array:
template<unsigned int N>
class Foo {
public:
Foo()
{
_nums = new int[N](); //allocate and zeo-initialized
}
Foo(const Foo<N>& other)
{
_nums = new int[N];
for (int i = 0; i < N; ++i) _nums[i] = other._nums[i];
}
Foo(Foo<N>&& other)
{
_nums = other._nums; //move the resource
other._nums=0; //make it null
}
Foo<N> operator=(const Foo<N> & other); //implement it!
virtual ~Foo() { delete [] _nums; }
private:
int *_nums;
};
Why do I have to provide default ctor if I want to create an array of objects of my type?
Thanks for answers
Because they have to be initialized.
Consider if it wasn't the case:
struct foo
{
foo(int) {}
void bar(void) {}
};
foo a[10];
foo f = a[0]; // not default-constructed == not initialized == undefined behavior
Note you don't have to:
int main(){
// initializes with the int constructor
foo a[] = {1, 2, 3};
}
// if the constructor had been explicit
int main(){
// requires copy-constructor
foo a[] = {foo(1), foo(2), foo(3)};
}
If you really need an array of objects and you can't give a meaningful default constructor, use std::vector.
If you really need an array of of objects, can't give a meaningful default constructor, and want to stay on the stack, you need to lazily initialize the objects. I have written such a utility class. (You would use the second version, the first uses dynamic memory allocation.)
For example:
typedef lazy_object_stack<foo> lazy_foo;
lazy_foo a[10]; // 10 lazy foo's
for (size_t i = 0; i < 10; ++i)
{
// create a foo, on the stack, passing `i` to the constructor
a[i].create(i);
}
for (size_t i = 0; i < 10; ++i)
a[i].get().bar(); // and use it
// automatically destructed, of course
The default constructor will be called for each object in the array.
You don't have to specify a default constructor as one will be created for you.
Just make sure you don't declare a constructor with no parameters as private or protected.
Here's an example of one being created for you:
class C
{
};
C c[10];
Whereas if you make it private you get a compiling error:
class C
{
private:
C()
{
}
};
C c[10];
When defining an array, you cannot specify ctor parameter, hence every object in the array must be constructed using the default ctor.
Normally, the C++ compiler will create the default ctor for you automatically. But, if you define a ctor with parameters, then the automatically creation of the default ctor is supressed, and you must explicitly write one.
Because when the array is initialized, default constructors are called for its items.