surprising constructors for a class!

S

Srinu

Hi,

What is the problem here in this code?
It gives segmentation fault. I found value of size in vector (int *a)
is no more 3. How is this?



==============
#include <iostream>

using namespace std;

class vector
{
int *v;
int size;
public:
vector(int m)
{
v = new int[size = m];
for(int i=0; i<size; i++)
v = 0;
}
vector (int *a)
{
for(int i=0; i<size; i++)
v = a;
}
int operator*(vector &y)
{
int sum = 0;
for(int i=0; i<size; i++)
sum += this -> v * y . v;
return sum;
}
};

int main()
{
int x[3] = {1,2,3};
int y[3] = {4,5,6};
vector v1(3);
vector v2(3);
v1 = x;
v2 = y;
int R = v1 * v2;
cout << "R = " << R;
return 0;
}

Sincerely,
Srinivas Nayak
 
S

Stefan van Kessel

==============
#include<iostream>

using namespace std;

class vector
{
int *v;
int size;
public:
vector(int m)
{
v = new int[size = m];
for(int i=0; i<size; i++)
v = 0;
}
vector (int *a)
{
for(int i=0; i<size; i++)
v = a;
}
int operator*(vector&y)
{
int sum = 0;
for(int i=0; i<size; i++)
sum += this -> v * y . v;
return sum;
}
};

int main()
{
int x[3] = {1,2,3};
int y[3] = {4,5,6};
vector v1(3);
vector v2(3);
v1 = x;
v2 = y;
int R = v1 * v2;
cout<< "R = "<< R;
return 0;
}

Sincerely,
Srinivas Nayak


What happens when you write v1 = x; is that vector(int *a) is called to
create a temporary vector which then is assigned to v1 by calling the
operator= which is generated for you by the compiler. In vector(int *a)
v is uninitialized and you are writing to some random memory location
(undefined behavior). Later the compiler generated operator= copies over
the v and size from the temporary, overwriting the values that were in
v1. At this point you loose the dynamically allocated v1.v pointer
(memory leak).

For the code you wrote to properly function you need to write a custom
assignment operator and destructor and even though you're not using the
copy constructor in the testcase you posted, in keeping with the so
called "rule of three", you should also write a custom copy constructor.

When you dynamically allocate memory you should always think about
whether the pointers you are using actually point to memory you already
initialized and you should always delete[] the memory at the latest when
you are about to loose the last pointer to it.

Have a nice day,
Stefan
 
G

gwowen

        v1 = x;

When you do this assignment, the compiler constructs a new temporary
vector out of the arrays x[]. In effect, it does this

vector xtmp(x); // (1)
v1 = xtmp; // (2)

Line (1) calls vector::vector(int*) which never sets xtmp.size or
xtmp.v or allocates any memory. Then it copies an indeterminate
amount from x[] (xtmp.size isn't initialized) to an indeterminate
location (xtmp.v isn't initialised).
Line (2) then calls the implicit operator=, which doesn't work as you
expect either.
 
S

Srinu

What happens when you write v1 = x; is that vector(int *a) is called to
create a temporary vector which then is assigned to v1 by calling the
operator= which is generated for you by the compiler.


will creation of temporary vector will happen even if I provide a
operator= ?
 
F

Francesco S. Carta

Yeah, very good idea. Very good idea.

I was about to point out just the same thing.

If the OP misses to catch the irony, I'll tell it explicitly: the std
namespace includes a template called std::vector. Importing the whole
std namespace into the global one and then creating stuff using the same
names of other stuff contained by the std namespace is _absolutely not_
a good idea - this could raise misleading error messages, conflicting
names, and so on, that wouldn't be fun debugging.
 
S

Stefan van Kessel

will creation of temporary vector will happen even if I provide a
operator= ?

If you only write a vector& operator=(const vector& r) then the
temporary will still be created and all that changes is that your own
operator=(const vector& r) will be called instead of the compiler
generated one. If you also write a vector& operator=(int *a), then
instead of creating the temporary and assigning it, the operator= taking
a int* will be called.

When you write "v1 = x;" that's the same as writing "v1.operator=(x);".
At this point the compiler starts looking for a vector::eek:perator= that
takes an argument of the type of x. If there is one i.e. operator=(int
*a), that operator is used. If there isn't such a operator= the compiler
goes on looking for a way to convert x to a type for which a operator=
exists. In your case vector::vector(int *a) does offer a conversion from
int* to vector so it is used. If you want to know the exact rules
governing implicit conversion sequences, look at 13.3.3.1 in the standard.

In addition to revisiting your book's chapters on constructors,
assignment operators and destructors, you might benefit from reading the
following article: http://www.drdobbs.com/cpp/184401400 ("C++ Made
Easier: The Rule of Three" by Andrew Koenig and Barbara E. Moo)

Have a nice day,
Stefan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top