runtime error

Sep 1, 2009 at 9:27am
Hi all,

Can somebody tell me why this code does not work and how to fix it? It compiles but runtime errors appear:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <iostream>
#include <vector>
using namespace std;  

template <class T>
class Vec
{
public:
  // constructors
  Vec(int length); 
  Vec(int length, T typeValue); 
  Vec(const Vec<T>& rhsObj); 
  const Vec<T>& operator=(const Vec<T>& rhsObj);
  const Vec<T>& operator=(T& typeValue);
  const Vec<T>& operator*=(T typeVal);
  const Vec<T> operator*(T typeVal) const;
  const T& operator()(int index) const;
  T& operator()(int index);
  int getSize() const;
  ~Vec();
private:
  vector<T> myVec_;
};


template<class T> 
Vec<T>::
Vec(int length)
{
  myVec_ = vector<T>(length);
}

template<class T> 
Vec<T>::
Vec(int length, T typeValue)
{
  myVec_ = vector<T>(length,typeValue);
}

template<class T> 
Vec<T>::
Vec(const Vec<T>& rhsObj) 
{
  vector<T> myVec_(rhsObj.myVec_);
}

template<class T> 
const Vec<T>& 
Vec<T>::
operator=(const Vec<T>& rhsObj)
{
  myVec_ = rhsObj.myVec_;
  return *this;
}

template<class T> 
const Vec<T>& 
Vec<T>::
operator=(T& typeValue)
{
  for (unsigned i = 0; i < myVec_.size(); i++)
    (*this)(i) = typeValue;
  return *this;
}

template<class T>
const Vec<T>&
Vec<T>::
operator*=(T typeVal)
{  
  for (unsigned i = 0; i < myVec_.size(); i++)
  {
    (*this)(i) *= typeVal; 
  }
  return *this;
} 

template<class T>
const Vec<T>
Vec<T>::
operator*(T typeVal) const
{
  return (Vec<T>(*this) *= typeVal);
} 

template<class T>
const T&
Vec<T>::
operator()(int index) const
{
  return myVec_[index];
} 

template<class T>
T&
Vec<T>::
operator()(int index)
{
  return myVec_[index];
} 

template<class T> 
int
Vec<T>::
getSize() const
{
  return (myVec_.size());
}

template<class T> 
Vec<T>::
~Vec()
{
}


// ******************************************************************************
// overloading externally since the first argument is not an object: typeVal*obj1
// ******************************************************************************
template<class T>
const Vec<T>
operator*(const T typeVal, const Vec<T>& obj1)
{
  return (obj1*typeVal);
}


int main()
{
  Vec<double> x(3,4);
  Vec<double> d = x*2.0;
  cout << d(0) << " " << d(1) << " " << d(2) << endl;
  return 0;
}
Sep 1, 2009 at 9:36am
You need to tell us what the error is and when it occurs
Sep 1, 2009 at 1:21pm
Your copy constructor is wrong.

You don't even need one; the default member-wise copy version provided by the compiler will suffice.
Sep 1, 2009 at 4:45pm
Thanks jsmith. The problem is in the copy constructor. I just commented it and now the code works. Just to understand a little bit more, why the copy constructor defined as above is wrong?

Thanks.
Sep 1, 2009 at 5:01pm
You are declaring a variable myVec_ inside the function that shadows the class member myVec_.
The assignment is assigning to the local variable, not to the class member.
Sep 1, 2009 at 5:08pm
1
2
3
4
5
6
template<class T> 
Vec<T>::
Vec(const Vec<T>& rhsObj) 
{
  vector<T> myVec_(rhsObj.myVec_);
}


Syntactically it looks like you are simply creating a temporary object within the constructor which happens to have the same name as the class attribute. Since this is the constructor, you'd want to use the initializer list. When it is all said and done, the object that was constructed has an empty myVec_ object. Then you try to make a call to its operator() function will attempts to access an empty vector using its operator[] which causes undefined behavior. You can confirm this by setting breakpoints and stepping into the copy constructor and operator() functions (assuming that they weren't inlined by the compiler). Anyway, as jsmith indicates the copy constructor and assignment operator aren't necessary.
Sep 1, 2009 at 6:33pm
ok. thanks jsmith and kempofighter. Now, the correct constructor is:

1
2
3
4
5
6
template<class T> 
Vec<T>::
Vec(const Vec<T>& rhsObj) 
{
  myVec_ = rhsObj.myVec_;
}

or
1
2
3
4
5
template<class T> 
Vec<T>::
Vec(const Vec<T>& rhsObj) :  myVec_ (rhsObj.myVec_)
{
}


Also, is there any way I can do the following in the main() function:
1
2
3
4
5
6
7
int main()
{
  Vec<double> x(3,4);
  Vec<double> d = 2*x;
  cout << d(0) << " " << d(1) << " " << d(2) << endl;
  return 0;
}

without incurring in a compilation error because of 2 can be interpreted as more than one type? I mean I would like this to compile independently if I use 2*x or 2.0*x

Thanks again.

Sep 1, 2009 at 7:10pm
user Robertlzw suggested me this:

1
2
3
4
5
6
template<class T, class U>
const Vec<T>
operator*(const U typeVal, const Vec<T>& obj1)
{
  return (obj1*typeVal);
}

which actually works pretty good.
Thanks.
Topic archived. No new replies allowed.