Returning a pointer to a struct

D

djcredo

Hey all,

I want to return a pointer to a struct. Here is what I'lm trying to do:

struct Position{
int x;
int y;
};

Position* GraphicTag::getRenderCentre(){
int cenx = m_renderPosition->x + m_size->width / 2;
int ceny = m_renderPosition->y + m_size->height / 2;

return (Position *){cenx,ceny}; // <---- Error here
}

I get "Error: initializer for scalar variable requires one element".
I'm a Java programmer at heart, and still a little uneasy around
pointers.

Thanks,
Matt
 
I

int2str

I want to return a pointer to a struct. Here is what I'lm trying to do:

struct Position{
int x;
int y;
};

Position* GraphicTag::getRenderCentre(){
int cenx = m_renderPosition->x + m_size->width / 2;
int ceny = m_renderPosition->y + m_size->height / 2;

return (Position *){cenx,ceny}; // <---- Error here
}

I get "Error: initializer for scalar variable requires one element".
I'm a Java programmer at heart, and still a little uneasy around
pointers.

With a simple data structure like this, it does not make much sense to
use pointers at all. In C++, I would personally try to return a simple
structure like this by value or by reference first, and only as a last
resort would I use pointers.

You get the error since a pointer in C++ needs (or should) point to
something. In other words, you need to create a valid object to point
to first.

Your structure also has no applicable default constructor that could
help you here. You should consider adding one.

And finally, if you have this function create a "Position" object and
return a pointer to it, the caller will be responsible for deleting the
object - not necessarily a desired behaiour.

Alf P. Steinbach (frequent contributor in this group) has a good
tutorial on C++ pointers:
http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf

Cheers,
Andre
 
V

Victor Bazarov

I want to return a pointer to a struct. Here is what I'lm trying to
do:

struct Position{
int x;
int y;
};

Position* GraphicTag::getRenderCentre(){
int cenx = m_renderPosition->x + m_size->width / 2;
int ceny = m_renderPosition->y + m_size->height / 2;

return (Position *){cenx,ceny}; // <---- Error here
}

I get "Error: initializer for scalar variable requires one element".
I'm a Java programmer at heart, and still a little uneasy around
pointers.

Pointers are good when you have objects addresses of which you can
take and assign to those pointers. Your "{cenx,ceny}" syntax is not
C++. If you want to move along in C++, you'll need to un-learn some
of Java.

In this particular case do NOT return a pointer. Return an object:

Position GraphicTag::getRenderCentre(){
Position retval = { m_renderPosition->x + m_size->width/2,
m_renderPosition->x + m_size->height/2 };
return retval;
}

Of course, it's better to make your Position to have a c-tor that
would take two values and construct a temporary right in the
return expression.

struct Position{
int x;
int y;
Position(int xx, int yy) : x(xx), y(yy) {}
};

...
return Position( m_renderPosition..../2, m_render.../2 );
}

There are implications about adding your own c-tor to the struct,
so you decide which path to take.

V
 
D

djcredo

Thank you both,

Firstly, what is the scope of a struct which is created (not as a
pointer) in a member function? I always thought it was local only
(would delete when the function is returned), but I'm clearly wrong
here. Does it last until the object that the member function belongs to
is destroyed?

Secondly, am I correct in thinking that there is no "inline" way of
creating a pointer to a struct like I was trying to, unless I define a
constructor? (I'm very stubborn, even if it isn't the right way, I like
to know where I was going wrong with the syntax).

Thanks again,
Matt
 
G

Gavin Deane

Thank you both,

Firstly, what is the scope of a struct which is created (not as a
pointer) in a member function? I always thought it was local only
(would delete when the function is returned), but I'm clearly wrong
here. Does it last until the object that the member function belongs to
is destroyed?

The object created within the function has the scope of that function
and is indeed destroyed [*] at the end of that function. However, when
you return by value as Victor suggested, a whole new, entirely separate
object is created for the return value. So by the end of the function,
the local object has been destroyed, but that doesn't matter because
the return value is a different object that was created as a copy of
the local object while the local object still existed.

[*] Destroyed, not deleted. delete in C++ has a very specific meaning
(as a keyword, in all lower case). It is what you do to objects with
dynamic storage duration (those created with new) when you, the
programmer, decide it is time for them to cease existing.

Gavin Deane
 
V

Victor Bazarov

[..]
Secondly, am I correct in thinking that there is no "inline" way of
creating a pointer to a struct like I was trying to, unless I define a
constructor?

You can use syntax Position() for a default-initialised temporary, if
it can, the compiler declares and defines the default constructor for
you. In your case it doesn't make sense, of course.
(I'm very stubborn, even if it isn't the right way, I
like to know where I was going wrong with the syntax).

Well, the curly-brace enclosed initialiser list syntax is only used
(and available) in _declarations_, not in expressions. The 'return'
statement includes an expression. You can, as you know _declare_
(and define) your struct as

Position blah = { 1, 2 };

Here the "{ 1, 2 }" is the allowed initialiser syntax. You cannot
do, for example

foo( { 1, 2} );

(for some function 'foo' that takes 'Position' as its argument). It
is not allowed. If you need to create a temporary object and give it
some non-default value, the class has to define a c-tor, so you
can use the syntax

foo( Position(1,2) );

, for example.

V
 
S

Salt_Peter

Thank you both,

Firstly, what is the scope of a struct which is created (not as a
pointer) in a member function? I always thought it was local only
(would delete when the function is returned), but I'm clearly wrong
here. Does it last until the object that the member function belongs to
is destroyed?

A struct doesn't have a scope - it doesn't exist. An instance of a
struct does.
The local variable dies with the function but if you return the
variable, a copy ctor creates a brand new object in main for you.
Secondly, am I correct in thinking that there is no "inline" way of
creating a pointer to a struct like I was trying to, unless I define a
constructor? (I'm very stubborn, even if it isn't the right way, I like
to know where I was going wrong with the syntax).

Thanks again,
Matt

Look at it this way. If you *could* use a pointer, you'ld be much
better off using a const reference instead. Pointers are responsible
for most of the bugs that programs suffer from. Even in the case of
allocations, pointers should be replaced by smart_ptr(s) and references
work nicely with polymorphism.
A C++ programmer'ss ultimate goal is (or should be) to write an entire
application without ever directly using a pointer. The resulting code
will be safer, bug-proof, easily maintainable and effortlessly
expandable/extendable.

The solution: a const reference. The only viable alternative is return
by copy. Are you ready? Cause there is a moral to the story...

#include <iostream>

class Position {
int x, y;
public:
Position() : x(0), y(0)
{
std::cout << "Position()\n";
}
Position(int x_, int y_) : x(x_), y(y_)
{
std::cout << "Position(int, int)\n";
}
Position(const Position& copy)
{
std::cout << "copy Position\n";
x = copy.x;
y = copy.y;
}
int getx() const { return x; }
int gety() const { return y; }
};

class Graphic
{
Position pos; // precious coordinate
public:
Graphic() : pos() { }
void move(const Position& r_pos)
{
pos = r_pos;
}
const Position& getpos() const // by const ref
{
return pos;
}
};

int main()
{
Graphic graphic;
graphic.move( Position(10,10) );
Position gpos = graphic.getpos();
std::cout << "pos.x = " << gpos.getx();
std::cout << "\npos.y = " << gpos.gety();
std::cout << std::endl;
}

/*
Position() // 0,0
Position(int, int) // 10,10
copy Position // the reference is copied safely
pos.x = 10
pos.y = 10
*/

Graphic's getpos() above is a viable candidate for a pointer return
since its returning an internal member. Thing is: why would i want a
user of the class to have *access* to my precious graphic's Position?
Even if it were to be accessed + modified by accident? You could return
a constant pointer - but then some smart-ass can const_cast<> your
precious position into oblivion. I'm not joking - i'm dead serious.

Consider:

Position* const Graphic::getpos() // by constant pointer
{
return &pos;
}

some smart ass could write the following side-effect:

*graphic.getpos() = Position(-1,-1); // modifies your private member
!!!

and screw you royally. Try it. Even if getpos() is made const, i can
*still* modify the internal position with a Postion ptr and a
const_cast<>.

Forget doing that with a const reference. Its absolutely nuke-proof.
 
S

Steve Pope

Salt_Peter said:
A struct doesn't have a scope - it doesn't exist.

Sure it does. Try compiling the following.

void foo () {
{
struct goo {
int a;
};
goo b; // legal
}
goo c; // illegal, causes 'goo undeclared'
}

Steve
 
S

Salt_Peter

Steve said:
Sure it does. Try compiling the following.

void foo () {
{
struct goo {
int a;
};
goo b; // legal

dandy, but hardly the context at hand.
And lets not get confused with an instance's scope, type visibilty and
type accessibility.
What you have above is a struct in a closed anonymous namespace.

namespace GOO {
struct goo { };
}

void foo () {
GOO::goo b;
}

GOO::goo c;

int main()
{
GOO::goo d;
}
 
S

Steve Pope

Salt_Peter said:
Steve Pope wrote:
dandy, but hardly the context at hand.
And lets not get confused with an instance's scope, type visibilty and
type accessibility.

You're right that my point does not address the OP's concern, however
your statement above seemed to imply that you believe a structure
declaration (as opposed to the definition of an instance of the
structure) doesn't have scope. It does, and can be (among perhaps
other possibilities) either global to a file or local to a block.
What you have above is a struct in a closed anonymous namespace.

namespace GOO {
struct goo { };
}

void foo () {
GOO::goo b;
}

GOO::goo c;

int main()
{
GOO::goo d;
}

I'm not sure I totally agree that names local to a block are
identical in behavior to names in an anonymous namespace. For one
thing, a name can be declared in an anonymous namespace and then used
outside the namespace's block but within the same file.

They are somewhat different scoping mechanisms.

Steve
 
E

eriwik

Hey all,

I want to return a pointer to a struct. Here is what I'lm trying to do:

struct Position{
int x;
int y;

};Position* GraphicTag::getRenderCentre(){
int cenx = m_renderPosition->x + m_size->width / 2;
int ceny = m_renderPosition->y + m_size->height / 2;

return (Position *){cenx,ceny}; // <---- Error here

}I get "Error: initializer for scalar variable requires one element".
I'm a Java programmer at heart, and still a little uneasy around
pointers.

I'd just like to add, if you haven't figured it out already, that in
principle there are two instances where you can return a pointer. The
first is if you have a class/struct with a member, then you can return
a pointer to that member, but as Salt_Peter has pointed out, this is
generally not a good idea. The second instance is when you dynamically
allocate memory for some type, in which case you get a pointer:

Position* GraphicTag::getRenderCentre(){
Position* pos = new Position; // OBS!
pos->x = m_renderPosition->x + m_size->width / 2;
pos->y = m_renderPosition->y + m_size->height / 2;

return pos;
}

As others have pointed out, this is generally a bad idea, the memory
allocated by new will not get freed until you call delete on a
Position-pointer that points to it (like the one returned from
getRenderCentre()), should you loose this pointer you have a
memory-leek. In general, every new shall have a delete, the problem is
that you only call new in one place but you often might need to delete
in several places. This leads to two problems, either you don't delete
where you should, and you get a memory-leek, or you try to use a
pointer that has already deleted, in which case (if you are lucky) the
program will crash (if you are unlucky anything could happen).
 
S

Steve Pope

I'd just like to add, if you haven't figured it out already, that in
principle there are two instances where you can return a pointer. The
first is if you have a class/struct with a member, then you can return
a pointer to that member, but as Salt_Peter has pointed out, this is
generally not a good idea. The second instance is when you dynamically
allocate memory for some type, in which case you get a pointer:

Actually, there's a third situation when you can return a pointer:
it can point to a static or global object. That's in a sense
the safest type of pointer to return.

Steve
 
D

djcredo

Wow, this has been a very enlightening thread, thank you all who have
made time to post and write code examples!

Every new user should read this thread - many C++ books / tuts tell you
how to "code", but don't tell you how to "build software" if you know
what I mean. Rules like this should be committed to memory.

I have one final question if you would:

I have a class GraphicTag which has a member of type Tag (a class, not
struct). Both the Tag and GraphicTag objects are created in the main()
function, then the Tag is passed to the GraphicTag constructor:

int main(){

Tag tag(10,5);
GraphicTag gTag(// pass tag here to constructor);

}

My question is, how is it best to store the Tag inside the GraphicTag,
and hence, how is it best to pass it in the constructor? The Tag object
won't be changed inside the main() function; once it's passed to the
GraphicTag, it is left alone from the main() function's point of view.
Is it possible to do this:

int main(){
Tag* tag = new Tag(10,5);
GraphicTag gTag(tag);
}

class GraphicTag {
protected:
Tag m_tag;
};

GraphicTag::GraphicTag(Tag* tag){
m_tag = *tag; // m_tag is now the instance of the
created tag.
}

.... and is this even the best way?

Thanks again,
Matt
 
E

eriwik

Wow, this has been a very enlightening thread, thank you all who have
made time to post and write code examples!

Every new user should read this thread - many C++ books / tuts tell you
how to "code", but don't tell you how to "build software" if you know
what I mean. Rules like this should be committed to memory.

I have one final question if you would:

I have a class GraphicTag which has a member of type Tag (a class, not
struct). Both the Tag and GraphicTag objects are created in the main()
function, then the Tag is passed to the GraphicTag constructor:

int main(){

Tag tag(10,5);
GraphicTag gTag(// pass tag here to constructor);

}My question is, how is it best to store the Tag inside the GraphicTag,
and hence, how is it best to pass it in the constructor? The Tag object
won't be changed inside the main() function; once it's passed to the
GraphicTag, it is left alone from the main() function's point of view.
Is it possible to do this:

int main(){
Tag* tag = new Tag(10,5);
GraphicTag gTag(tag);

}class GraphicTag {
protected:
Tag m_tag;

};GraphicTag::GraphicTag(Tag* tag){
m_tag = *tag; // m_tag is now the instance of the
created tag.

}... and is this even the best way?

You could, but once again, a pointer is not the best way to do it.
There are two "problems" with this approach, first you use dynamic
allocated memory (new) when you don't have to, the second is that if
the tag created in main() won't change, you don't have to store a copy
of it in GraphicTag, you can store the thing itself (or rather a
reference to it).

class GraphicTag {
protected:
Tag& m_tag; // notice the &, a reference
};

GraphicTag::GraphicTag(Tag& tag){
m_tag = tag; // m_tag is now a reference to the tag
created in main
}

int main(){
Tag tag(10,5);
GraphicTag gTag(tag);
}

Read up on references, they can often be used where a pointer can be
used, and in those cases a reference is almost always preferable. A
note on style: try to keep at least the closing '}' on a separate line,
it will make the code easier to read.
 
E

eriwik

On Dec 1, 11:39 am, "(e-mail address removed)"
note on style: try to keep at least the closing '}' on a separate line,
it will make the code easier to read.

Disregard that, seems it's only google messing up the code.
 
D

djcredo

Thank you, I am now much more clued-in about pointers and references. I
am very greatful! I will aim to use references much more now (I had
completely overlooked them and just jumped into pointers)!

Thanks again,
Matt
 
G

Gavin Deane

I have a class GraphicTag which has a member of type Tag (a class, not
struct). Both the Tag and GraphicTag objects are created in the main()
function, then the Tag is passed to the GraphicTag constructor:

int main(){

Tag tag(10,5);
GraphicTag gTag(// pass tag here to constructor);

}

My question is, how is it best to store the Tag inside the GraphicTag,
and hence, how is it best to pass it in the constructor? The Tag object
won't be changed inside the main() function; once it's passed to the
GraphicTag, it is left alone from the main() function's point of view.

What do you mean by "it is left alone from the main() function's point
of view"? Do you mean main does not touch the Tag object, does not
change it, does not pass it to any other functions or objects, does not
care in any way about it after the GraphicTag is created? If so, then
the Tag is logically owned by the GraphicTag and should not even exist
in main.

class Tag
{
public:
Tag(int a, int b) {}
// ...
};

class GraphicTag
{
public:
GraphicTag(int tag_param_1, int tag_param_2) :
tag(tag_param_1, tag_param_2) {}
// ...
private:
Tag tag;
// ...
};

int main()
{
GraphicTag gTag(10, 5);
}

Gavin Deane
 
G

Gavin Deane

Read up on references, they can often be used where a pointer can be
used, and in those cases a reference is almost always preferable.

As long as that doesn't contradict the ownership semantics of the
design. I saw nothing in the original question to suggest that the
simplest solution, holding a member object rather than holding a
reference or pointer, was inappropriate.

Gavin Deane
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,017
Latest member
GreenAcreCBDGummiesReview

Latest Threads

Top