template

Y

yashwant pinge

#include<iostream>

using namespace std;

template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

int length() const
{
return size;
}
};

class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}
operator float const()
{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};

template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}

T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}

int length() const
{
return size;
}

~Holder()
{
delete np;
}
};

int main()
{
Holder<Number> h;

for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?

for(int j=0;j<2;j++)
cout<<h[j]<<endl;

return 0;
}


Why the number constructor is called during the execution of line
" h=i;"
 
J

Jim Langston

yashwant pinge said:
#include<iostream>

using namespace std;

template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

int length() const
{
return size;
}
};

class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}
operator float const()
{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};

template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}

T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}

int length() const
{
return size;
}

~Holder()
{
delete np;
}
};

int main()
{
Holder<Number> h;

for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?

for(int j=0;j<2;j++)
cout<<h[j]<<endl;

return 0;
}


Why the number constructor is called during the execution of line
" h=i;"


Look at operator[] for Holder.

T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}

It's sayign if np does not yet exist (the constructor initializes it to
null) then to call operator new on it. In this case it would be:
np = new Array<Number, 2>
( the 2 comes from the template's 2nd parameter, if not passed is defaulted
to 2).
so the first time (when i == 0) 2 Numbers will be constructed and copied to
the Array, hence your number constructor being called.
 
Y

yashwant pinge

#include<iostream>
using namespace std;
template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}
int length() const
{
return size;
}
};
class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}
operator float const()
{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};
template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}
T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}
int length() const
{
return size;
}
~Holder()
{
delete np;
}
};
int main()
{
Holder<Number> h;
for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?

for(int j=0;j<2;j++)
cout<<h[j]<<endl;
return 0;
}
Why the number constructor is called during the execution of line
" h=i;"


Look at operator[] for Holder.

T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}

It's sayign if np does not yet exist (the constructor initializes it to
null) then to call operator new on it. In this case it would be:
np = new Array<Number, 2>
( the 2 comes from the template's 2nd parameter, if not passed is defaulted
to 2).
so the first time (when i == 0) 2 Numbers will be constructed and copied to
the Array, hence your number constructor being called.


GDB gives the formate of called Number constructor
after h[0]=0
Number (this=0xbfffe2a8, ff=0) at 6.cpp:26
and h[1]=1
Number (this=0xbfffe2a8, ff=1) at 6.cpp:26

why it is..?
 
R

Robert Bauck Hamar

yashwant said:
#include<iostream>

using namespace std;

template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

Often you would also want a
const T& operator[](int) const
too.
int length() const
{
return size;
}
};

class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}

This operator=() would be written by the compiler if you hadn't written it
yourself.
operator float const()

Why not
operator float() const
?
{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};

template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}

T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}

int length() const
{
return size;
}

~Holder()
{
delete np;
}

You should take care. The compiler will generate
Holder(const Holder& other) : np(other.np) {}
and
Holder& operator=(const Holder& other) { np = other.np; }

If one of these are invoked, you would delete np twice. In addition, the
assignment operator is bound to leak memory. Remember the rule of three: A
class with any of {destructor, assignment operator, copy constructor}
generally needs all 3.
};

int main()
{
Holder<Number> h;

invokes Holder said:
for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?


h calls Holder<Number>::eek:perator[](int). The first time this
executes, !np is false, and an Array<Number, 2> is default constructed.
This creates an array of size 2 of Number, which constructs these two
numbers with Number::Number(0.0f), since this is the default constructor of
number.

Holder<Number>::eek:perator[](int) then returns a reference to a Number object.
This number is assigned to, which means a call to Number::eek:perator=(const
Number&), which is the only assignment operator defined. This assignment
operator can use a temporary Number object, and this is constructed by
first converting i to a float, and then using this float as an argument to
Number::Number(float). That is:

h = i;

means

h.operator[](i).operator=(Number(float(i)))
for(int j=0;j<2;j++)
cout<<h[j]<<endl;

return 0;
}


Why the number constructor is called during the execution of line
" h=i;"
 
Y

yashwant pinge

yashwant said:
#include<iostream>
using namespace std;
template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

Often you would also want a
const T& operator[](int) const
too.


int length() const
{
return size;
}
};
class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}

This operator=() would be written by the compiler if you hadn't written it
yourself.
operator float const()

Why not
operator float() const
?


{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};
template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}
T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}
int length() const
{
return size;
}
~Holder()
{
delete np;
}

You should take care. The compiler will generate
Holder(const Holder& other) : np(other.np) {}
and
Holder& operator=(const Holder& other) { np = other.np; }

If one of these are invoked, you would delete np twice. In addition, the
assignment operator is bound to leak memory. Remember the rule of three: A
class with any of {destructor, assignment operator, copy constructor}
generally needs all 3.
int main()
{
Holder<Number> h;

invokes Holder<Number>::Holder().


for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?


h calls Holder<Number>::eek:perator[](int). The first time this
executes, !np is false, and an Array<Number, 2> is default constructed.
This creates an array of size 2 of Number, which constructs these two
numbers with Number::Number(0.0f), since this is the default constructor of
number.

Holder<Number>::eek:perator[](int) then returns a reference to a Number object.
This number is assigned to, which means a call to Number::eek:perator=(const
Number&), which is the only assignment operator defined. This assignment
operator can use a temporary Number object, and this is constructed by
first converting i to a float, and then using this float as an argument to
Number::Number(float). That is:

h = i;

means

h.operator[](i).operator=(Number(float(i)))
for(int j=0;j<2;j++)
cout<<h[j]<<endl;
return 0;
}
Why the number constructor is called during the execution of line
" h=i;"



Breakpoint 1, main () at 6.cpp:72
72 Holder<Number> h;
(gdb) step
Holder (this=0xbfffe2b0) at 6.cpp:49
49 {
(gdb) step
main () at 6.cpp:74
74 for(int i=0;i<2;i++)
(gdb) step
75 h=i;
(gdb) step
Number (this=0xbfffe2a8, ff=0) at 6.cpp:26
26 {
(gdb) step
27 }
(gdb) step
Holder<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0) at 6.cpp:54


I could not understand the flow of the code that GDB is given me
why the num constructor is called before
"older<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0)"
 
Y

yashwant pinge

yashwant said:
#include<iostream>
using namespace std;
template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

Often you would also want a
const T& operator[](int) const
too.


int length() const
{
return size;
}
};
class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}

This operator=() would be written by the compiler if you hadn't written it
yourself.
operator float const()

Why not
operator float() const
?


{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};
template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}
T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}
int length() const
{
return size;
}
~Holder()
{
delete np;
}

You should take care. The compiler will generate
Holder(const Holder& other) : np(other.np) {}
and
Holder& operator=(const Holder& other) { np = other.np; }

If one of these are invoked, you would delete np twice. In addition, the
assignment operator is bound to leak memory. Remember the rule of three: A
class with any of {destructor, assignment operator, copy constructor}
generally needs all 3.
int main()
{
Holder<Number> h;

invokes Holder<Number>::Holder().


for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?


h calls Holder<Number>::eek:perator[](int). The first time this
executes, !np is false, and an Array<Number, 2> is default constructed.
This creates an array of size 2 of Number, which constructs these two
numbers with Number::Number(0.0f), since this is the default constructor of
number.

Holder<Number>::eek:perator[](int) then returns a reference to a Number object.
This number is assigned to, which means a call to Number::eek:perator=(const
Number&), which is the only assignment operator defined. This assignment
operator can use a temporary Number object, and this is constructed by
first converting i to a float, and then using this float as an argument to
Number::Number(float). That is:

h = i;

means

h.operator[](i).operator=(Number(float(i)))
for(int j=0;j<2;j++)
cout<<h[j]<<endl;
return 0;
}
Why the number constructor is called during the execution of line
" h=i;"



Breakpoint 1, main () at 6.cpp:72
72 Holder<Number> h;
(gdb) step
Holder (this=0xbfffe2b0) at 6.cpp:49
49 {
(gdb) step
main () at 6.cpp:74
74 for(int i=0;i<2;i++)
(gdb) step
75 h=i;
(gdb) step
Number (this=0xbfffe2a8, ff=0) at 6.cpp:26
26 {
(gdb) step
27 }
(gdb) step
Holder<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0) at 6.cpp:54


I could not understand the flow of the code that GDB is given me
why the num constructor is called before
"older<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0)"
 
R

Robert Bauck Hamar

yashwant said:
yashwant said:
#include<iostream>
using namespace std;
template<class T, int size=100>
class Array
{
T array[size];
public:
T& operator [](int index)
{
return array[index];
}

Often you would also want a
const T& operator[](int) const
too.


int length() const
{
return size;
}
};
class Number
{
float f;
public:
Number(float ff=0.0f):f(ff)
{
}
Number& operator =(const Number& n)
{
f=n.f;
return *this;
}

This operator=() would be written by the compiler if you hadn't written
it yourself.
operator float const()

Why not
operator float() const
?


{
return f;
}
friend ostream& operator <<(ostream& os,const Number& x)
{
return os << x.f;
}
};
template<class T,int size=2>
class Holder
{
Array<T,size>*np;
public:
Holder():np(0)
{
}
T& operator [](int i)
{
if(!np) np = new Array<T,size>;
return np ->operator[](i);
}
int length() const
{
return size;
}
~Holder()
{
delete np;
}

You should take care. The compiler will generate
Holder(const Holder& other) : np(other.np) {}
and
Holder& operator=(const Holder& other) { np = other.np; }

If one of these are invoked, you would delete np twice. In addition, the
assignment operator is bound to leak memory. Remember the rule of three:
A class with any of {destructor, assignment operator, copy constructor}
generally needs all 3.
int main()
{
Holder<Number> h;

invokes Holder<Number>::Holder().


for(int i=0;i<2;i++)
h=i; // why the number constructor
called ...?


h calls Holder<Number>::eek:perator[](int). The first time this
executes, !np is false, and an Array<Number, 2> is default constructed.
This creates an array of size 2 of Number, which constructs these two
numbers with Number::Number(0.0f), since this is the default constructor
of number.

Holder<Number>::eek:perator[](int) then returns a reference to a Number
object. This number is assigned to, which means a call to
Number::eek:perator=(const Number&), which is the only assignment operator
defined. This assignment operator can use a temporary Number object, and
this is constructed by first converting i to a float, and then using this
float as an argument to Number::Number(float). That is:

h = i;

means

h.operator[](i).operator=(Number(float(i)))
for(int j=0;j<2;j++)
cout<<h[j]<<endl;
return 0;
}
Why the number constructor is called during the execution of line
" h=i;"



Breakpoint 1, main () at 6.cpp:72
72 Holder<Number> h;
(gdb) step
Holder (this=0xbfffe2b0) at 6.cpp:49
49 {
(gdb) step
main () at 6.cpp:74
74 for(int i=0;i<2;i++)
(gdb) step
75 h=i;
(gdb) step
Number (this=0xbfffe2a8, ff=0) at 6.cpp:26
26 {
(gdb) step
27 }
(gdb) step
Holder<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0) at 6.cpp:54


I could not understand the flow of the code that GDB is given me
why the num constructor is called before
"older<Number, 2>::eek:perator[](int) (this=0xbfffe2b0, i=0)"


Because the standard says that the order of evaluation is unspecified. That
is, the compiler may choose in which order the arguments are calculated.
 

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,982
Messages
2,570,185
Members
46,738
Latest member
JinaMacvit

Latest Threads

Top