scope of objects returned by value

Are objects which are constructed in a return statement *always* created in the temporary of the caller rather than copied to the temporary? (i.e. is it portable?)

Cheers,
Bryan

The following code works on the two compilers I've tested it with... VC++ 7.1 and MacOS Xcode (g++):

class A {
public:
int value() { return _value; } private:A(int v) : _value(v) { }

A() { crash(); }
A(const A &) { crash(); }
operator =(const A &) { crash(); }

friend class B;
volatile int _value;
};

class B {
public:
static A getA() { return A(987654); } };

int result = B::getA().value(); // result == 987654
[699 byte] By [bmoodie] at [2007-11-19 6:03:47]
# 1 Re: scope of objects returned by value
bm,

The member function value() makes a copy of _value and returns this to the calling function using the standard return mechanism of the compiler. The code looks portable, however some of the design idioms such as the use of the volatile keyword seem a bit akward.

Sincerely, Chris.

:)
dude_1967 at 2007-11-9 0:41:11 >
# 2 Re: scope of objects returned by value
Hey dude,

Sorry, perhaps I should have explained my code better...
The value() function was merely to show that the object of class A is accessible and volatile was just paranoia to avoid optimization. :)

The important part is the member function getA() which returns an A via "return A(987654)".
To make it impossible to copy an A, I made all constructors and the assignment operator private, only granting B the right to create an A as a friend.

What actually happens is the caller pushes an address onto the stack and the getA() method constructs the A object at that address.
So my question is whether or not this direct contruction in the caller's temporary is portable or not.
Otherwise shouldn't the copy constructor be called? :confused:

Thanks,
- Bryan
bmoodie at 2007-11-9 0:42:16 >
# 3 Re: scope of objects returned by value
Hey dude,
What actually happens is the caller pushes an address onto the stack and the getA() method constructs the A object at that address.
So my question is whether or not this direct contruction in the caller's temporary is portable or not.
Otherwise shouldn't the copy constructor be called? :confused:

Thanks,
- BryanThe code you posted is OK. As long as the object being returned has proper copy semantics, the code works. The compiler is free to do any optimization it believes it can make on the return value. One such optimization is called Return-Value-Optimation or RVO, where there is no temporary at all that's created.

The only issue you must be concerned with is if your copy constructor or assignment operator has some sort of side-effect that depends on whether the copy constructor or assignment operator is called. Again, the reason being that the compiler can optimize away creation of temporaries if it sees fit. No C++ programmer would even write code like that, so I don't think you have anything to worry about.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-9 0:43:18 >
# 4 Re: scope of objects returned by value
Thanks Paul, :D

If a copy/assignment is called is it within the scope of the function who is returning the object? (with respect to access privileges)

This would mean you could return a "pointer" object from a method which is usable but not copyable by client code.

Cheers
- Bryan
bmoodie at 2007-11-9 0:44:18 >
# 5 Re: scope of objects returned by value
The copy / assignment is within the scope of the function in which the copy / assignment statement exists.

And yes indeed, a particular misuse of C/C++ as you correctly pointed out can open up all kinds of problems if a pointer to a temporary object is returned from a function. The temporary object will go out of scope according to the scope of the function and the returned pointer will point to something which is undefined such as addressable stack space. The example below shows this kind of problem and this example can be expanded so as to pertain to your last question.

Sincerely, Chris.

const char* p_string(void)
{
auto const char strHelloWorld[] = "Hello World!";

// Not a good idea.
return &strHelloWorld[0];
}
dude_1967 at 2007-11-9 0:45:17 >
# 6 Re: scope of objects returned by value
Hey Chris,

That's not what I was meaning... maybe I'm just a bad communicator - who knows. :)

Here's an explicit example of what I was meaning by a pointer object:


template <class T>
class Pointer {
public:

T * operator ->() { return _pointer; }

private:
Pointer(T *pointer) : _pointer(pointer) { /* acquire */ }
Pointer(const Pointer<T> &other) : _pointer(other._pointer) { }

~Pointer() { /* release */ }

friend class Manager;

T *_pointer;
};


So given the following...
class Foo {
public:
void doStuff() {}
};

class Manager {
public:
Manager() : _myFoo(new Foo) { }
// ...
Pointer<Foo> currentItem() { return Pointer<Foo>( _myFoo.get() ); }

private:
auto_ptr<Foo> _myFoo;
};

void testCode()
{
Manager manager;
manager.currentItem()->doStuff(); // valid

// Pointer<Foo> fooPtr1 = manager.currentItem(); // invalid
// Pointer<Foo> fooPtr2( manager.currentItem() ); // invalid
}
...does the currentItem() method make the copy of Pointer<Foo> or does the caller, testCode() make the copy? I know that my compiler makes the copy in currentItem() but can I rely on this?

The idea being that it's a pointer you can use but not copy in anyway.
This makes it possible to have pre-method and post-method code in one place without modifying the object you are pointing at. e.g. acquire/release, validation, synchronization, etc...

So is it always true that this copy happens in the method which returns the object? i.e. currentItem()

Thanks, Bryan
bmoodie at 2007-11-9 0:46:18 >
# 7 Re: scope of objects returned by value
Have you tried to compile your code? Your code will not compile if the destructor in Pointer is private:

#include <memory>
template <class T>
class Pointer {
public:

T * operator ->() { return _pointer; }

private:
Pointer(T *pointer) : _pointer(pointer) { /* acquire */ }
Pointer(const Pointer<T> &other) : _pointer(other._pointer) { }

~Pointer() { /* release */ }

friend class Manager;

T *_pointer;
};

class Foo {
public:
void doStuff() {}
};

class Manager {
public:
Manager() : _myFoo(new Foo) { }
// ...
Pointer<Foo> currentItem() { return Pointer<Foo>( _myFoo.get() ); }

private:
std::auto_ptr<Foo> _myFoo;
};
void testCode()
{
Manager manager;
manager.currentItem()->doStuff(); // valid

// Pointer<Foo> fooPtr1 = manager.currentItem(); // invalid
// Pointer<Foo> fooPtr2( manager.currentItem() ); // invalid
}

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for ONLINE_EVALUATION_BETA1
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"ComeauTest.c", line 35: error: "Pointer<T>::~Pointer() [with T=Foo]" is
inaccessible
manager.currentItem()->doStuff(); // valid
^

1 error detected in the compilation of "ComeauTest.c".

...does the currentItem() method make the copy of Pointer<Foo> or does the caller, testCode() make the copy? I know that my compiler makes the copy in currentItem() but can I rely on this?I think you're reading too much into this. The function manager.currentItem() returns a Pointer<foo> object. You are then accessing the doStuff() member function from the returned object. Honestly, I don't see how much more can be said about a simple concept of a function returning an object.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-9 0:47:24 >
# 8 Re: scope of objects returned by value
I do compile the code before posting it - obviously I added the destructor just before sending - my bad... i should be dragged across hot coals apparently. :p

It was a VERY simple question, but no one answered it.
(does a copy via 'return' use the caller's access permissions or the callee?)

Thanks for your help anyway. :wave:
- Bryan
bmoodie at 2007-11-9 0:48:22 >
# 9 Re: scope of objects returned by value
It was a VERY simple question, but no one answered it.
(does a copy via 'return' use the caller's access permissions or the callee?)The problem with the question is that it doesn't use familiar C++ nomenclature, even though it may sound simple. For example, what do you mean by "access permissions"? To a C++ programmer, an access specifier is private, public, or protected. A term such as "access permissions" just doesn't click or is not used in C++ discussions, which is why your question is confusing.

In any event, the called function, on return, creates a copy and returns the object. In some cases, the creation of the copy is not done and RVO optimization is used instead.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-9 0:49:20 >
# 10 Re: scope of objects returned by value
It was a VERY simple question, but no one answered it.
(does a copy via 'return' use the caller's access permissions or the callee?)

currentItem() returns a Pointer<Foo> object. Regardless of the fact that the object wraps a pointer, it is an object, and not a pointer. So a copy of the pointer<Foo> object will be made and that copy will be assigned to the Pointer<Foo> object in testCode() (through the copy constructor).
HighCommander4 at 2007-11-9 0:50:29 >