is it possible/ok to return a const reference even if the value the function returns is a local variable of this function? i know that locals are not valid anymore once the function returns - but what if the function is inlined and the returned value is only used within the callers scope? then the locals of the function should be included in the callers stackframe, no?
Don't count on it. Even if this works on 1 compiler, it's not standard supported behavior and is likely to break on others.
No, it's not OK. Local variables are declared on the stack, and the stack keeps changing between method calls. Also, the objects that get out of scope get destroyed. Always return a copy of a local variable.
Consider this code:
#include <iostream>
using namespace std;
class MyClass
{
public:
MyClass() { cout << "ctor" << endl; }
~MyClass() { cout << "dtor" << endl; }
MyClass(const MyClass& r) { cout << "copy" << endl; }
};
const MyClass& Test()
{
MyClass m;
return m;
}
int main()
{
cout << "before Test" << endl;
MyClass m = Test();
cout << "after Test" << endl;
}
This will print out:
before Test
ctor
dtor
copy
after Test
dtor
The object you're trying to copy has already called its destructor and may be in an invalid state.
inline is not a guarantee -- it's a suggestion. Even if you use tricks to force inline, you'll never be sure about the result, especially if you want to remain portable.
Hence, don't do it.
Doing that invokes undefined behaviour.
There's no way of forcing a compiler to inline the function. inline is just a suggestion - so is __forceinline
Even if you could guarantee that the function would be inlined, the destructor for the variable in question will still be executed, leaving you with a reference to a dead object.
And the big one - C++'s concept of the stack is delimited by scope - not by function.
#include <iostream>
int main()
{
{
int a = 5;
std::cout << std::hex << "0x" << &a << std::endl;
}
{
int b = 10;
std::cout << std::hex << "0x" << &b << std::endl;
}
}
My compiler puts 'a' and 'b' at different memory address. Except when I turn optimizations on. Yours may well decide that it's an optimization to reuse the memory your object previously occupied.
Is there a paticular problem you're trying to solve here? There are other ways of reducing the number of temporary objects created if that's your concern.
As others have noted, this is dangerous. It's also unnecessary, if your compiler supports the NRVO (Named Return Value Optimization), and your function uses and returns the local variable you would have liked to return by ref in a fairly simple way.
The NRVO allows the compiler to avoid copy construction under certain conditions - typically the main reason to avoid returning objects by value. VC++ 8 supports this (a delta on previous revisions) and it makes quite a bit of perf diff in frequently used code.
The value falls out of scope when the callee falls out of scope. So no, it is gone.
But if you want a fairly ugly solution (and a red flag warning you that your design might need refactoring), you can do something like this:
const MyObj& GetObj()
{
static const MyObj obj_;
return obj_;
}
...but this solution if fraught with peril, especially if the object is modifyable, or does something non-trivial in a multithreaded environment.
The inline keyword doesn't guarantee that the function is really inlined. Don't do it.
Related
I know the title sounds familiar as there are many similar questions, but I'm asking for a different aspect of the problem (I know the difference between having things on the stack and putting them on the heap).
In Java I can always return references to "local" objects
public Thing calculateThing() {
Thing thing = new Thing();
// do calculations and modify thing
return thing;
}
In C++, to do something similar I have 2 options
(1) I can use references whenever I need to "return" an object
void calculateThing(Thing& thing) {
// do calculations and modify thing
}
Then use it like this
Thing thing;
calculateThing(thing);
(2) Or I can return a pointer to a dynamically allocated object
Thing* calculateThing() {
Thing* thing(new Thing());
// do calculations and modify thing
return thing;
}
Then use it like this
Thing* thing = calculateThing();
delete thing;
Using the first approach I won't have to free memory manually, but to me it makes the code difficult to read. The problem with the second approach is, I'll have to remember to delete thing;, which doesn't look quite nice. I don't want to return a copied value because it's inefficient (I think), so here come the questions
Is there a third solution (that doesn't require copying the value)?
Is there any problem if I stick to the first solution?
When and why should I use the second solution?
I don't want to return a copied value because it's inefficient
Prove it.
Look up RVO and NRVO, and in C++0x move-semantics. In most cases in C++03, an out parameter is just a good way to make your code ugly, and in C++0x you'd actually be hurting yourself by using an out parameter.
Just write clean code, return by value. If performance is a problem, profile it (stop guessing), and find what you can do to fix it. It likely won't be returning things from functions.
That said, if you're dead set on writing like that, you'd probably want to do the out parameter. It avoids dynamic memory allocation, which is safer and generally faster. It does require you have some way to construct the object prior to calling the function, which doesn't always make sense for all objects.
If you want to use dynamic allocation, the least that can be done is put it in a smart pointer. (This should be done all the time anyway) Then you don't worry about deleting anything, things are exception-safe, etc. The only problem is it's likely slower than returning by value anyway!
Just create the object and return it
Thing calculateThing() {
Thing thing;
// do calculations and modify thing
return thing;
}
I think you'll do yourself a favor if you forget about optimization and just write readable code (you'll need to run a profiler later - but don't pre-optimize).
Just return a object like this:
Thing calculateThing()
{
Thing thing();
// do calculations and modify thing
return thing;
}
This will invoke the copy constructor on Things, so you might want to do your own implementation of that. Like this:
Thing(const Thing& aThing) {}
This might perform a little slower, but it might not be an issue at all.
Update
The compiler will probably optimize the call to the copy constructor, so there will be no extra overhead. (Like dreamlax pointed out in the comment).
Did you try to use smart pointers (if Thing is really big and heavy object), like shared_ptr:
std::shared_ptr calculateThing()
{
std::shared_ptr<Thing> thing(new Thing);
// .. some calculations
return thing;
}
// ...
{
std::shared_ptr<Thing> thing = calculateThing();
// working with thing
// shared_ptr frees thing
}
One quick way to determine if a copy constructor is being called is to add logging to your class's copy constructor:
MyClass::MyClass(const MyClass &other)
{
std::cout << "Copy constructor was called" << std::endl;
}
MyClass someFunction()
{
MyClass dummy;
return dummy;
}
Call someFunction; the number of "Copy constructor was called" lines that you will get will vary between 0, 1, and 2. If you get none, then your compiler has optimised the return value out (which it is allowed to do). If you get don't get 0, and your copy constructor is ridiculously expensive, then search for alternative ways to return instances from your functions.
Firstly you have an error in the code, you mean to have Thing *thing(new Thing());, and only return thing;.
Use shared_ptr<Thing>. Deref it as tho it was a pointer. It will be deleted for you when the last reference to the Thing contained goes out of scope.
The first solution is very common in naive libraries. It has some performance, and syntactical overhead, avoid it if possible
Use the second solution only if you can guarantee no exceptions will be thrown, or when performance is absolutely critical (you will be interfacing with C or assembly before this even becomes relevant).
I don't want to return a copied value because it's inefficient
This may not be true. Compilers can do optimisation to prevent this copying.
For example, GCC does this optimisation. In the following program, neither move constructor nor copy constructor are called, since no copying or moving is done. Also, notice the address of c. Even though the object c is instantiated inside the function f(), c resides in the stack frame of main().
class C {
public:
int c = 5;
C() {}
C(const C& c) {
cout << "Copy constructor " << endl;
}
C(const C&& c) noexcept {
cout << "Move Constructor" << endl;
}
};
C f() {
int beforeC;
C c;
int afterC;
cout << &beforeC << endl; //0x7ffee02f26ac
cout << &c << endl; //0x7ffee02f2710 (notice: even though c is instantiated inside f(), c resides in the stack frame of main()
cout << &afterC << endl; //0x7ffee02f26a8
return c;
}
C g() {
C c = f(); ///neither copy constructor nor move constructor of C are called, since none is done
cout << &c << endl; //0x7ffee02f2710
return c;
}
int main() {
int beforeC;
C c = g(); ///neither copy constructor nor move constructor of C are called, since none is done
int afterC;
cout << &beforeC << endl; //0x7ffee02f2718
cout << &c << endl; //0x7ffee02f2710 (notice:even though c is returned from f,it resides in the stack frame of main)
cout << &afterC << endl; //0x7ffee02f270c
return 0;
}
I'm sure a C++ expert will come along with a better answer, but personally I like the second approach. Using smart pointers helps with the problem of forgetting to delete and as you say, it looks cleaner than having to create an object before hand (and still having to delete it if you want to allocate it on the heap).
Consider the following program:
class C {
...
};
const C f() {
C ret;
cout << &ret << endl;
return ret;
}
int main() {
C value = f();
cout << &value << endl;
}
result: // note the address are the same
0x7ffdd24b26e0
0x7ffdd24b26e0
The variable 'ret' in function f() and variable 'value' has the same memory address so it seems 'value' is not a copy of 'ret'. The variable 'ret' is a stack variable so it should be invalidated after f() returns. So why c++ allow returning a stack value inside a function?
g++ version:
g++ (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4
The reason for the address of ret and value being the same is the so called Return Value Optimization (RVO). It means that in this case a copy is not going to be performed. Note however, that you can not rely on this, as it is not bound to happen (although that will change with C++17 [at least the current draft]).
https://en.wikipedia.org/wiki/Return_value_optimization
This is an example of copy-elision, specifically RVO (return value optimization). It allows you to avoid the performance penalty of returning an object.
I've worked with a lot of people who were unaware of RVO and wrote stuff like:
void get_stuff(std::vector<int>& foo /*and input params*/) {
// add a whole lot of integers into foo.
}
because they thought this would be cheaper (by avoiding a copy) than:
void get_stuff(/*input params*/){
std::vector foo;
// populate foo.
return foo;
}
This leads to unnecessarily verbose, and often difficult to read code. It's quintessential premature optimization -- a mistake you won't be making, since you now know about RVO!
Returning the function result by value is one of the places, where the compiler is allowed to elide a copy as an optimization and thus translates your code to the moral equivalent of this :
void f(uint8_t* memory) {
new(memory) C; // create object reserved memory location
cout << (size_t)memory << endl;
}
int main() {
alignas(alignof(C)) uint8_t value[sizeof(C)]; //<- reserve properly aligned raw storage of appropriate size on the stack
f(value);
cout << (size_t)&value[0] << endl;
}
This optimization technique is called NRVO (named return value optimization) and is actually a pretty natural consequence of most calling conventions which specify that - for values that can't be returned via a register - the returned value is put at an address that is specified by the caller anyway.
I'm not sure whether this is actually RVO. An equally valid hypothesis is that the storage of both ret and value is on the implementation's stack, and that they share the same stack slot because their lifetimes are effectively non-overlapping. There might have been an intermediary.
I often read I should pass a shared_ptr by const reference to a function, because its faster. When I think about it I am not sure if this is a realy good advice, because I am not sure if this would be threadsave. Can anybody tell me if this would be threadsave to pass by const ref?
You should prefer passing by const& to avoid the overhead of a copy of any class. For example, this is particularly important for stuff like std::string.
In the case of passing a shared_ptr by const& the overhead is mostly the incrementing and decrementing of the reference count because it's atomic.
BUT! There is a gotcha when creating a thread with const& shared_ptr: the reference count will be incremented. Since it is incremented, it's almost like if you had passed it by value. You are in fact passing by-value to the std::thread ctor, thus the increment, then passing by ref to the function.
See for yourself:
// gcc (Ubuntu 4.8.4-2ubuntu1~14.04.1) 4.8.4
void test(const shared_ptr<int>& i)
{
cout << "c = " << i.use_count() << endl;
}
int main(int argc, char** argv)
{
shared_ptr<int> i(new int);
cout << "c = " << i.use_count() << endl;
test(i);
cout << "thread!" << endl;
thread t(test, i);
t.join();
cout << "c = " << i.use_count() << endl;
}
The results being:
c = 1
c = 1
thread!
c = 2 // <= incremented!
c = 1 // <= thread joined!
shared_ptr is a perfect candidate for thread-safety but it will not protect you from race-conditions and dead-locks.
With a & you get the object itself.
You are not increased the ref count, you just pass over the object it self. The reason people suggest to pass by const& is to avoid the costs of thread-safely increasing the ref count. The cost when passing as a const& is same cost as copying an int or a pointer, and no temporary object will be bound to the const& as the constructor of the shared_ptr is marked explicit.
And because you will always have at least 1 reference to the object (the object the reference is bound to from the callee function) there is no fear the object might be destroyed while you use the local reference.
Passing by const reference is thread-agnostic. Look at following simple code:
void foo(const std::shared_ptr<int>& x) {
sleep(100000);
}
void bar() {
//...
std::shared_ptr y = ...;
foo(y);
}
y is going to live in the bar until foo returns - thus making sure shared_ptr remains valid. If foo() were to create another thread and pass x to it, it will have to copy it - and this will increase reference counter.
Passing by reference is always thread safe, no matter what object gets passed. And it is irrelevant if it is a reference to const or not.
My friend told me C++ allows us to call a member function even if the instance is destroyed from memory. So I write the code below to verify it, but why the value of a can be extracted even after the object was destroyed? I thought there would be a segment fault.
#include <iostream>
class Foo{
public:
Foo(int a = 0){
std::cout << "created" << std::endl;
this->a = a;
}
~Foo(){
std::cout << "destroyed" << std::endl;
}
Foo *f(){
std::cout << "a=" << a << std::endl;
return this;
}
private:
int a;
};
Foo *iwanttocallf(int i){
return ((Foo)i).f();
}
int main(){
for(int i = 0; i < 3; i++)
iwanttocallf(i)->f();
}
Output from my Macbook Air:
created
a=0
destroyed
a=0
created
a=1
destroyed
a=1
created
a=2
destroyed
a=2
Usually compilers are implementing the member function call as a call to a regular c function with the first argument a pointer to the object (gcc does it like that as far as I know). Now if your pointer is pointing to one destroyed object it doesn't mean that the memory where the a has been stored will be changed, it might be changed. So it is undefined behavior in general. In your case you got a value of a but maybe next time with a different compiler or different code you will crash. Try to use placement new operator then set a value of 'a' = 0 in destructor... and follow the memory where the object is stored.
"My friend told me C++ allows us to call a member function even if the member is destroyed from memory"?
I don't know what your friend is trying to say. But you call member function on some object of a class
unless it's a static member. So, if you delete that object from memory, how could you call any function of that class on that object. It's an undefined behavior.
This is covered in ยง12.7 [class.cdtor]:
[..] For an object with a non-trivial destructor, referring to any non-static member or base class of the object after the destructor
finishes execution results in undefined behavior.
As other people have told, this involves undefined behavior, and any result is possible. I'll try to explain why you encountered this particular result (stuff working normally).
Objects in C++ are represented by contents of memory. When an object is destroyed, its
destructor is executed, but the memory still contains the previous value. The output operation outputs the value taken from memory (which is now "free" - doesn't belong to any object) - if there is not much stuff going on between the destructor call and the output, the old value will remain.
However, if you change your code to add some calculations, the bug will be evident. For example, I added the following function that simulates some calculations:
int do_stuff()
{
int result = 0;
int x[3] = {0};
for (auto& n: x)
{
n = rand();
result ^= n;
}
return result;
}
I also added a call to this function:
Foo *f(){
std::cout << "foo1: a=" << a << std::endl;
do_stuff();
std::cout << "foo2: a=" << a << std::endl;
return this;
}
I got the output:
foo1: a=0
foo2: a=424238335
This clearly shows that it's not safe to expect anything consistent when dealing with deleted objects.
By the way, some debuggers overwrite the memory that deleted objects occupied with a special value like 0xcdcdcdcd - to make some sense out of this kind of unpredictable behavior. If you execute your code under such a debugger, you will see garbage printed, and will immediately know that your code is buggy.
I know the title sounds familiar as there are many similar questions, but I'm asking for a different aspect of the problem (I know the difference between having things on the stack and putting them on the heap).
In Java I can always return references to "local" objects
public Thing calculateThing() {
Thing thing = new Thing();
// do calculations and modify thing
return thing;
}
In C++, to do something similar I have 2 options
(1) I can use references whenever I need to "return" an object
void calculateThing(Thing& thing) {
// do calculations and modify thing
}
Then use it like this
Thing thing;
calculateThing(thing);
(2) Or I can return a pointer to a dynamically allocated object
Thing* calculateThing() {
Thing* thing(new Thing());
// do calculations and modify thing
return thing;
}
Then use it like this
Thing* thing = calculateThing();
delete thing;
Using the first approach I won't have to free memory manually, but to me it makes the code difficult to read. The problem with the second approach is, I'll have to remember to delete thing;, which doesn't look quite nice. I don't want to return a copied value because it's inefficient (I think), so here come the questions
Is there a third solution (that doesn't require copying the value)?
Is there any problem if I stick to the first solution?
When and why should I use the second solution?
I don't want to return a copied value because it's inefficient
Prove it.
Look up RVO and NRVO, and in C++0x move-semantics. In most cases in C++03, an out parameter is just a good way to make your code ugly, and in C++0x you'd actually be hurting yourself by using an out parameter.
Just write clean code, return by value. If performance is a problem, profile it (stop guessing), and find what you can do to fix it. It likely won't be returning things from functions.
That said, if you're dead set on writing like that, you'd probably want to do the out parameter. It avoids dynamic memory allocation, which is safer and generally faster. It does require you have some way to construct the object prior to calling the function, which doesn't always make sense for all objects.
If you want to use dynamic allocation, the least that can be done is put it in a smart pointer. (This should be done all the time anyway) Then you don't worry about deleting anything, things are exception-safe, etc. The only problem is it's likely slower than returning by value anyway!
Just create the object and return it
Thing calculateThing() {
Thing thing;
// do calculations and modify thing
return thing;
}
I think you'll do yourself a favor if you forget about optimization and just write readable code (you'll need to run a profiler later - but don't pre-optimize).
Just return a object like this:
Thing calculateThing()
{
Thing thing();
// do calculations and modify thing
return thing;
}
This will invoke the copy constructor on Things, so you might want to do your own implementation of that. Like this:
Thing(const Thing& aThing) {}
This might perform a little slower, but it might not be an issue at all.
Update
The compiler will probably optimize the call to the copy constructor, so there will be no extra overhead. (Like dreamlax pointed out in the comment).
Did you try to use smart pointers (if Thing is really big and heavy object), like shared_ptr:
std::shared_ptr calculateThing()
{
std::shared_ptr<Thing> thing(new Thing);
// .. some calculations
return thing;
}
// ...
{
std::shared_ptr<Thing> thing = calculateThing();
// working with thing
// shared_ptr frees thing
}
One quick way to determine if a copy constructor is being called is to add logging to your class's copy constructor:
MyClass::MyClass(const MyClass &other)
{
std::cout << "Copy constructor was called" << std::endl;
}
MyClass someFunction()
{
MyClass dummy;
return dummy;
}
Call someFunction; the number of "Copy constructor was called" lines that you will get will vary between 0, 1, and 2. If you get none, then your compiler has optimised the return value out (which it is allowed to do). If you get don't get 0, and your copy constructor is ridiculously expensive, then search for alternative ways to return instances from your functions.
Firstly you have an error in the code, you mean to have Thing *thing(new Thing());, and only return thing;.
Use shared_ptr<Thing>. Deref it as tho it was a pointer. It will be deleted for you when the last reference to the Thing contained goes out of scope.
The first solution is very common in naive libraries. It has some performance, and syntactical overhead, avoid it if possible
Use the second solution only if you can guarantee no exceptions will be thrown, or when performance is absolutely critical (you will be interfacing with C or assembly before this even becomes relevant).
I don't want to return a copied value because it's inefficient
This may not be true. Compilers can do optimisation to prevent this copying.
For example, GCC does this optimisation. In the following program, neither move constructor nor copy constructor are called, since no copying or moving is done. Also, notice the address of c. Even though the object c is instantiated inside the function f(), c resides in the stack frame of main().
class C {
public:
int c = 5;
C() {}
C(const C& c) {
cout << "Copy constructor " << endl;
}
C(const C&& c) noexcept {
cout << "Move Constructor" << endl;
}
};
C f() {
int beforeC;
C c;
int afterC;
cout << &beforeC << endl; //0x7ffee02f26ac
cout << &c << endl; //0x7ffee02f2710 (notice: even though c is instantiated inside f(), c resides in the stack frame of main()
cout << &afterC << endl; //0x7ffee02f26a8
return c;
}
C g() {
C c = f(); ///neither copy constructor nor move constructor of C are called, since none is done
cout << &c << endl; //0x7ffee02f2710
return c;
}
int main() {
int beforeC;
C c = g(); ///neither copy constructor nor move constructor of C are called, since none is done
int afterC;
cout << &beforeC << endl; //0x7ffee02f2718
cout << &c << endl; //0x7ffee02f2710 (notice:even though c is returned from f,it resides in the stack frame of main)
cout << &afterC << endl; //0x7ffee02f270c
return 0;
}
I'm sure a C++ expert will come along with a better answer, but personally I like the second approach. Using smart pointers helps with the problem of forgetting to delete and as you say, it looks cleaner than having to create an object before hand (and still having to delete it if you want to allocate it on the heap).