This works:
MyClass MyNonRef;
MyNonRef(arg1, arg2); // works
But:
MyClass* MyNonRef = new MyClass;
MyNonRef(arg1, arg2); // doesn't work
MyNonRef->operator()(arg1, arg2); // works!
regards, r
the second definition of MyNonRef is a *pointer* to an instance of the class
MyClass.
(*MyNonRef)(arg1, arg2); // works
To use access any operator or member you have to dereference the
pointer.
MyNonRef.bar = 0; // doesn't work
(*MyNonRef).bar = 0; // works
MyNonRef->bar = 0; // works, it's the usual notation.
Regards,
Helge
"roger" <northso...@gmail.com> wrote in message
news:c520df2c-0e71-4d2b...@x37g2000yqj.googlegroups.com...
MyNonRef(arg1, arg2);
instead of
(*MyNonRef)(arg1, arg2);
I'm using a lot of mathematical type manipulations and it would help
if the code would be as (visually) clean as possible.
best regards, r
On Oct 16, 12:38 pm, "Helge Kruse" <Helge.Kruse-nos...@gmx.net> wrote:
> Hi Roger,
>
> the second definition of MyNonRef is a *pointer* to an instance of the class
> MyClass.
>
> (*MyNonRef)(arg1, arg2); // works
>
> To use access any operator or member you have to dereference the
> pointer.
>
> MyNonRef.bar = 0; // doesn't work
> (*MyNonRef).bar = 0; // works
> MyNonRef->bar = 0; // works, it's the usual notation.
>
> Regards,
> Helge
>
> "roger" <northsolomon...@gmail.com> wrote in message
>
> news:c520df2c-0e71-4d2b...@x37g2000yqj.googlegroups.com...
>
>
>
> > Hi,
> > Could someone please explain how I can user the overloaded operator()
> > for reference objects. I can do it for non-reference objects e.g.
>
> > This works:
> > MyClass MyNonRef;
> > MyNonRef(arg1, arg2); // works
>
> > But:
>
> > MyClass* MyNonRef = new MyClass;
>
> > MyNonRef(arg1, arg2); // doesn't work
> > MyNonRef->operator()(arg1, arg2); // works!
>
> > regards, r- Hide quoted text -
>
> - Show quoted text -
Top posting is usually discouraged. In interleave you remarks into
the reply rather than adding them at the top.
> Many thanks for you response, I see the error I made. But I'm still
> wondering if there a way that I could overload the operator so that I
> could write:
>
> MyNonRef(arg1, arg2);
>
> instead of
>
> (*MyNonRef)(arg1, arg2);
>
> I'm using a lot of mathematical type manipulations and it would help
> if the code would be as (visually) clean as possible.
Well then you do need a reference! Given a class MyType with ()
overloaded you can write:
MyType m;
m(arg1, arg2);
or
MyType *p = &m;
(*p)(arg1, arg2);
or what you probably want which is:
MyType &r = m;
r(arg1, arg2);
--
Ben.
Hi Roger,
You could try writing a class which wraps the pointer and giving it an
operator(). For example:
#include <iostream>
struct A
{
int i;
A(int i_) : i(i_) {}
};
class APtr
{
private:
A *m_p;
public:
APtr(A *p) : m_p(p) {}
operator A*()
{
return m_p;
}
operator const A*() const
{
return m_p;
}
A *operator->()
{
return m_p;
}
const A* operator->() const
{
return m_p;
}
void operator()()
{
std::cout << m_p->i << '\n';
}
};
int main()
{
A a(23);
A *p = &a;
APtr q = p;
q();
q->i = 9;
q();
return 0;
}
Regards,
Stu
Then correct the sardine heads, don't be one yourself.
> Hi Roger,
>
> You could try writing a class which wraps the pointer and giving it an
> operator(). For example:
Roger is a novice who as yet lacks knowledge of fundamentals.
He or she is not helped by such advice.
> #include <iostream>
>
> struct A
> {
> int i;
> A(int i_) : i(i_) {}
> };
>
> class APtr
> {
> private:
> A *m_p;
> public:
> APtr(A *p) : m_p(p) {}
>
> operator A*()
> {
> return m_p;
> }
>
> operator const A*() const
> {
> return m_p;
> }
This is a dubious and very misleading design. A raw pointer's constness does not
affect the constness of the pointed to object so you're at odds with the usual
conventions and the Principle of Least Surprise. Worse, this solution is not
even technically correct for the 'const' here is only a way to make usage even
more annoying: it does NOT prevent modification of the pointee, e.g.
foo( APtr const p )
{
APtr q = p;
*q = A(666);
}
It's easier to recognize the problem when you have seen it a number of times,
though, but simply remember this:
don't present solution code that you're unfamiliar with, for it will have
problems that you don't see.
>
> A *operator->()
> {
> return m_p;
> }
>
> const A* operator->() const
> {
> return m_p;
> }
>
> void operator()()
> {
> std::cout << m_p->i << '\n';
> }
Cheers & hth.,
- Alf
Sorry Alf. It seemed a tough call between consistency with what was
already there and posting at the bottom as I would usually - with
hindsight I guess the right option would have been to reformat all the
preceding posts, post at the bottom and add a comment.
>> Hi Roger,
>>
>> You could try writing a class which wraps the pointer and giving it an
>> operator(). For example:
>
> Roger is a novice who as yet lacks knowledge of fundamentals.
>
> He or she is not helped by such advice.
Apologies - the advice was meant well. I just saw a problem (effectively
"how do you get something which works like a pointer but can be called
like a function?") and hacked out some code. A little too quickly, by
the looks of things...
Ouch. You're right, of course :) I should have written the code more
carefully, since I meant:
operator A* const() const
>>
>> A *operator->()
>> {
>> return m_p;
>> }
>>
>> const A* operator->() const
>> {
>> return m_p;
>> }
Ditto here. I think I'm going to find an appropriate rock to crawl under
today.
Stu
For what it's worth, when I say "Ditto here", I mean:
A* const operator->() const
Stu
Many thanks for your reply.
Probably a stupid question then, but I always thought that you need to
use the "new" operator to get an object created on the heap and that
omitting the "new" operator puts the object on the stack. Does that
still hold?
As to top/bottom posting; I usually bottom post but since I was
grateful to the first person that responded to my question and she
seemed to prefer top posting I followed her preference.
regard, R
On Oct 16, 1:38 pm, Ben Bacarisse <ben.use...@bsb.me.uk> wrote:
Hi Alf,
Thanks for your reply, I learn a lot this way for which I am very
grateful!
I top posted because the first person that replied seemed to have a
preference for it and out of gratitude I followed her preference.
R
I am not sure what "still" means. You don't say what you think might
make that not hold.
Unfortunately it never does, but simply for technical reasons! new
crates and object with dynamic storage duration (i.e. it exists until
it is deleted or the program ends). This is the technical term for
"on the heap".
Omitting new gives you syntax error in most cases, but I know what you
mean. What you get is a declared object and it lifetime very much
depends on where that declaration occurs. If the declaration is
inside a function body (and it does not include either static or
extern), then the object will have automatic storage duration. This
is the technical way of saying "on the stack".
<snip>
--
Ben.
Ben,
Thanks again for your clarification, it does make sense. However one
point that I still cant't match with my previous experience is that I
remember that I ran into errors with stack overflows by creating large
arrays, e.g.
double array[large_number]; // fails for "large" arrays
double *pArray = array[large_number]; // works for arrays most that
aren't "very very large"
So this gave me the impression that I was working in different kinds
of memory depending on whether I was using the new operator or not
(i.e. heap vs. stack). Therefore I generally used the new operator for
large data variables but automatic variables only for small variables
like temporary loop variables etc.
Is it then right that an additional difference between stack and heap
is the amount of memory that is available?
best regards, R
C++ has a couple of operators called operator new and operator new[]. It
also has a couple of expressions called the new expression and the new
array expression. There is an imporatnt differnce between the first two
and the second two
The pure operators are used to acquire memory and nothing else. So:
void * memory_pool = operator new(100);
acquires a block of 100 bytes of memory from the 'heap manager'. In theory
void * memory_pool = operator new[](100);
does something similar but I cannor recall ever having seen it used. And
originally you could not overload operator new[] but as this can be
useful in cases of class specific memory acquisition the language does
allow you to overload it.
However direct use of the operators is expert territory (even though
quite common in expert code and in well written libraries)
The new expressions do something more.
mytype o_ptr = new mytype;
does two things. It first calls the relevant overload of operator new
for mytype to acquire a block of memory of sufficient size for a mytype
object. If this is successful it next calls the mytype ctor to construct
and instance of mytype in that storage and returns a pointer to mytype.
If it fails to acquire sufficient memory it goes into a recursive
routine to try to acquire it from other places the user has defined. If
all fails it normally throws an exception (though there are special
forms of operator new that return a null pointer)
mytype array = new mytype[array_size];
Does something similar in order to create an array. However almost
always you would be better advised to use a std::vector instead of a
dynamic array. (and in C++0x you can also use std::array)
That does not compile on any C or C++ compiler I have tried, nor should it.
Until array has been declared you should get an undefined symbol error
message and, of course, once it is defined you have the problem back again.
Anyway, stop using dynamic arrays and use std::vector instead.
Hi Francis,
Thanks for you reply, I forgot to type "new", so it should have been:
double *pArray = new array[large_number];
I would prefer to keep on using arrays simply because want to learn
and understand about them.
regards,
R
Hi Roger,
You're after this:
double *pArray = new double[large_number];
It's worth learning how dynamic arrays work, but in terms of what to use
on a day-to-day basis, Francis is right: a container like std::vector is
the way to go. Perhaps write some test programs to learn about dynamic
arrays, but use std::vector in any serious programs you write?
Regards,
Stu
My own slip-ups else-thread notwithstanding, ITYM:
mytype *o_ptr = new mytype;
> does two things. It first calls the relevant overload of operator new
> for mytype to acquire a block of memory of sufficient size for a mytype
> object. If this is successful it next calls the mytype ctor to construct
> and instance of mytype in that storage and returns a pointer to mytype.
> If it fails to acquire sufficient memory it goes into a recursive
> routine to try to acquire it from other places the user has defined. If
> all fails it normally throws an exception (though there are special
> forms of operator new that return a null pointer)
>
> mytype array = new mytype[array_size];
Similarly, ITYM:
mytype *array = new mytype[array_size];
Best wishes,
Stu
Thanks Stu,
Learning about arrays has already helped me tremendously where char
arrays are concerned. With the interfacing between programs, which I
use my small programs for, that is really very useful. I would still
like to understand the finer points about the difference between an
object created like this:
Object MyObject;
and one created like:
Object *MyObject = new Object;
in terms of memory usage limitations, since I've run into trouble
using statements like
double array[large_number];
but never like this:
double *parray = new double[large_number];
regards, R
> On Oct 17, 3:51 pm, Stuart Golodetz
In the following, I will use the term 'stack' for the memory area where
objects with automatic storage duration are stored and 'heap' for the
area containing dynamically allocated objects.
On a typical implementation, the address-space available to a program
will be divided into several parts. One part is for the objects with
static storage duration (such as global variables), one part for the
stack and, if the code shares the same address space as the data, a part
for the code. The remainder is left available for the heap.
Of these areas, the size needed for the code and the static variables is
known, but the stack and heap generally not. As the memory for the heap
can be shared between multiple processes (because in C++, there is a way
of signalling that the total amount of memory has run out) but the stack
memory can not be shared as easily, implementers invariably choose to
provide a rather small (initial) stack. For a modern PC, rather small
still means upwards of 4kB of stack.
With this in mind, the general advice is (when considering only memory
consumption):
- Store small (less than a couple of dozen bytes) and medium (less than
about a hundred bytes of bytes) objects on the stack
- Store arrays that can be considered a small or medium object on the
stack as well
- For everything else, use a container (arrays) or smart pointer (single
object) that manages the heap memory for you.
To correctly deal with manually allocated memory in the face of
exceptions is a difficult task that even the experts get wrong from time
to time.
Bart v Ingen Schenau
--
a.c.l.l.c-c++ FAQ: http://www.comeaucomputing.com/learn/faq
c.l.c FAQ: http://c-faq.com/
c.l.c++ FAQ: http://www.parashift.com/c++-faq-lite/
Bart,
Thanks _very_ much for taking the time to type up this explanation, it
really helps me in the learning process.
best regards, R
Hi Francis,
Thanks for the advice, it is indeed something I hadn't thought of
before but will try to keep in mind from now on.
best regards, R