`this` Pointer for Temporary [duplicate] - c++

This question already has answers here:
Why is taking the address of a temporary illegal?
(7 answers)
Closed 8 months ago.
Consider the following C++ code:
class Func {
public:
void operator()() const { std::cout << this; }
};
int main() {
Func()(); // OK
std::cout << &Func(); // Can't take address of a temporary
}
In the body of operator(), it is completely valid to treat this as any other pointer. However, we're told time and again that we can't take the address of a temporary, yet that seems to me to be exactly what's happening. The first line of main is perfectly fine, yet semantically, the line below it is identical. If I were to try to implement this in C to understand what's going on, I might dream up the following (C code):
typedef struct {} Func;
Func construct_Func() {
Func result;
return result;
}
void Func_operator_invoke(const Func* const this) {
printf("%p", this);
}
int main() {
Func_operator_invoke(&construct_Func()); // Can't take address of a temporary
}
Here, though, we run into a snag: we can't call our "simulated member function" on a temporary... which then begs the question -- why can we call member functions on temporaries in C++? If we can't take the address of a temporary, why can we pass the address of a temporary into a (member) function? Why is that any more valid than passing the address of a temporary into a free function?
Now, I fully expect that the answer to my question is "that's just how it is". That said, let me pose another question to preempt that answer: what does the standard say about calling member functions on temporary objects, and what is a reasonable way for a compiler to implement this? Could it simply push the temporary onto the stack, then pass the pointer to that memory to the function? If so, what's the reasoning behind the C and C++ standards not allowing similar behavior when taking the address of a temporary? As in, why doesn't the C code Func_operator_invoke(&(construct_Func())) simply create an object, then pass a pointer to that object? Is there a published or well-known reason at all?

There's nothing wrong with using this inside a member function. It's a valid pointer while that function is executing. The temporary object is destroyed after at the end of the full-expression (the ;).
So in Func()();
A temporary instance of Func is created
Func::operator() is executed
std::cout operator << is executed
The temporary is destroyed
This can't be reproduced with C as C has no classes nor member functions.
With regard to taking an address of a temporary, it's clearly an error as there's no possible valid use for it. For more details refer to Why is taking the address of a temporary illegal?

Related

Reassigning pointer argument inside function in C++ [duplicate]

This question already has answers here:
pass by reference and value with pointers [duplicate]
(5 answers)
Is passing pointer argument, pass by value in C++?
(5 answers)
Closed 10 months ago.
If I pass a pointer to a function as an argument and assign to the pointer inside the function, shouldn't that be reflected in the calling scope?
In the following code, s==nullptr gets printed. Why did assignment to s inside the function assign_string not reflected in the main function?
#include<iostream>
#include<string>
void assign_string(std::string* s)
{
s = new std::string("Reassigned");
}
int main()
{
std::string* s = nullptr;
assign_string(s);
if (s == nullptr)
{
std::cout << "s==nullptr" << std::endl;
}
else
{
std::cout << "s!=nullptr" << std::endl;
}
return 0;
}
PS: I'm new to C++ and I might be using terms like "assign" loosely.
EDIT.
Is passing pointer argument, pass by value in C++? has many useful answers.
If I pass a pointer to a function as an argument and assign to the pointer inside the function, shouldn't that be reflected in the calling scope?
No. When you pass an object by value, the parameter and the argument are separate objects. Modifying one object has no effect on the other object. This applies to all objects, including pointers.
In order to modify an object outside of the function, you need to use indirection. There are two forms of indirection: Pointers and references. So, in order to modify a pointer that is outside of the function, you need to pass a reference or a pointer to the pointer. Example:
void assign_string(std::string*& s);
PS: I'm new to C++
I recommend learning early that owning bare pointers are a bad idea and there is hardly ever a need to use them nor to use allocating new expressions. It's quite rare to need to dynamically allocate a std::string object or any other container.

C++: Looking for correction for "returning address of local variable..." [duplicate]

This question already has answers here:
Returning a reference to a local variable in C++
(3 answers)
Closed 2 years ago.
I am, currently, taking an online C++ class to fill my time while unemployed and I have a question concerning returning the address of a local variable. I realize that this is not a recommended practice and I'm looking for an alternate solution to what I'm trying to do (return data for copying into my object "co" which is a class Coord object). BTW ... the program works as far as results goes. But it does get the warning C4172 "returning address of local variable or temporary...". Can you help me out here?
HERE ARE THE DETAILS: In my homework program I have a function that returns the address of local variable Coord co (Coord is my constructed class with two int fields ... obviously ... coordinates). My goal was to use the Coord copy constructor to copy the data using the address of that local variable.
//The calling program declares object co of class Coord as follows
Coord co;
//calling program can makes the call to function requestMove() in a couple of places.
//here is one of the calls
co = bd.requestMove(pHuman);
//The signature of requestMove() is
const Coord& requestMove(Player&);
//The called function, requestMove(), has a local Coord object nodeAddress and it populates nodeAddress. The return statement is:
return nodeAddress;
Comments and suggestions would be welcome. Thanks, much.
the object will be destroyed after the scope exits, so it's memory is unallocated, and having an object pointing to that memory means it's undefined behavior. The most optimal solution would be to change the return statement to return Coord{args...}; and change the function signature to Coord requestMove(Player&); it will take advantage of guaranteed copy ellision meaning that auto co = bd.requestMove(pHuman); will result to auto co = Coord{args...};
You can return a reference to a temporary duration object, but this is just one of the ways to shoot oneself into the foot. C++ is not a nanny language and allows this.
Consider:
foo& bar() {
foo f;
return f;
}
This code will compile, but what happens? At first you create an object f, but when you return from bar, the object f goes out of scope and is destructed (this is the essence of RAII). The returned reference will be a 'wild reference' to the object that no longer exists, and trying to access that memory location is simply undefined behaviour (which is a nice way of saying that what the program will do -- nobody knows. For all intents and purposes it can crash, it can eat your cat or boil you coffee).
The compiler simply warns you that the code won't probably do what you expect it to do.
The correction would be to return the object by value here.
foo bar() {
foo f;
return f;
}

Setting std::function to nullptr from invoked callable target [duplicate]

This question already has answers here:
Is it safe to change a function pointer (std::function) inside a called function?
(2 answers)
Closed 4 years ago.
Is it legal C++ (this means without undefined behavior, etc.) to set a std::function variable to nullptr from the function/lambda expression stored to this variable when it was invoked?
My intention is to omit further invoking the of std::function.
#include <functional>
std::function<void(int)> func;
void setFunc(std::function<void(int)> f) {
func = f;
}
int main() {
setFunc([](int status) {
// do something...
setFunc(nullptr); // callback shall only be called once
});
for(;;) {
int status = 0;
// fetch status
if (func)
func(status);
}
}
Your question is an interesting twist on another one, namely:
Is delete this allowed?
The important part is carefully avoiding any use of the lambda's state afterwards.
Your lambda is stateless? That makes it simple.
But anyway, are you sure there's no cleaner alternative for your actual design? std::call_once() for example would be more obvious in this over-simplified example.
You can also set std::function<void(int)> object to a default-constructed one using an empty initializer list:
setFunc({});
To avoid assigning to the function object while it is being called, you may like to make a copy of it and invoke the copy.

How to pass parameters for output in C++ [duplicate]

This question already has answers here:
What are the differences between a pointer variable and a reference variable?
(44 answers)
Closed 9 years ago.
Some of methods that I see in C++ code are of this structure:
void Class::method1(int &a);
and are called like this:
int a;
class->method1(a);
But sometimes I see structures like:
void Class2::method2(int* a);
And these methods are called like this:
int a;
class2->method2(&a);
I understand that in the first case the method accepts an address of a variable, and in the second - pointer to a variable, right?
Could someone explain to me what is the difference between these two approaches, and when to use which?
Also, in the first example, it seems that a method can be taking "int& a" or "int a", and in both cases we would call it the same way: int a; class->method1(a); ? This seems confusing.
Thanks.
void Class::method1(int &a);
This is passing by reference.
void Class2::method2(int* a);
This is passing the pointer. In class2->method2(&a);, & is the address of operater.
First one is called using a reference to a variable, second one - using a pointer. There are some difference between the two concepts. I encourage you to google this, but the most important ones I can think of right now are that a reference can not be constructed without pointing to an existing object and that a pointer can be NULL.
void Class::method1(int &a) means you are passing a by reference and the caller can expect a to be modified.
void Class2::method2(int* a) means you are passing a by pointer and the caller can expect the thing to which a points to be modified.
Personally I don't like pass by reference since the caller doesn't quickly know if a will be modified as the calling syntax for pass by reference and pass by value are identical. Passing by constant reference void Class::method1(const int &a) is better still since then a cannot be modified and you can gain an efficiency in not taking value copies if a is a large object.
However many folk differ in their opinion and say that you should pass by pointer if the function allows the pointer to be null; i.e. can your function do something useful without a inputted?
In the first case, the method accept a reference to the variable.
It means that if a is modified inside the method1, it will be modified after the function returns.
In the second case, it accepts a pointer to the variable. A pointer is the memory adress of the variable. It's what the & retrieves : The address (aka a pointer to a).
Both type have essentially the same purpose : Being able to modify a variable of a different scope.
See that example :
void fooPointer (int* pointer) {
*pointer += 1;
}
void fooReference (int& reference) {
reference += 1;
}
int main () {
int a = 0;
std::cout << a; // Ouputs 0
fooPointer (&a);
std::cout << a; // Outputs 1
fooReference (a);
std::cout << a; // Outputs 2
}
As you can see, both allow you to do the same here. But using references is usually easier and more readable, because everything is done implicitly, so you don't have to reference (*) or dereference (&) your variables.

c++ unique_ptr argument passing

Suppose I have the following code:
class B { /* */ };
class A {
vector<B*> vb;
public:
void add(B* b) { vb.push_back(b); }
};
int main() {
A a;
B* b(new B());
a.add(b);
}
Suppose that in this case, all raw pointers B* can be handled through unique_ptr<B>.
Surprisingly, I wasn't able to find how to convert this code using unique_ptr. After a few tries, I came up with the following code, which compiles:
class A {
vector<unique_ptr<B>> vb;
public:
void add(unique_ptr<B> b) { vb.push_back(move(b)); }
};
int main() {
A a;
unique_ptr<B> b(new B());
a.add(move(b));
}
So my simple question: is this the way to do it and in particular, is move(b) the only way to do it? (I was thinking of rvalue references but I don't fully understand them.)
And if you have a link with complete explanations of move semantics, unique_ptr, etc. that I was not able to find, don't hesitate to share it.
EDIT According to http://thbecker.net/articles/rvalue_references/section_01.html, my code seems to be OK.
Actually, std::move is just syntactic sugar. With object x of class X, move(x) is just the same as:
static_cast <X&&>(x)
These 2 move functions are needed because casting to a rvalue reference:
prevents function "add" from passing by value
makes push_back use the default move constructor of B
Apparently, I do not need the second std::move in my main() if I change my "add" function to pass by reference (ordinary lvalue ref).
I would like some confirmation of all this, though...
I am somewhat surprised that this is not answered very clearly and explicitly here, nor on any place I easily stumbled upon. While I'm pretty new to this stuff, I think the following can be said.
The situation is a calling function that builds a unique_ptr<T> value (possibly by casting the result from a call to new), and wants to pass it to some function that will take ownership of the object pointed to (by storing it in a data structure for instance, as happens here into a vector). To indicate that ownership has been obtained by the caller, and it is ready to relinquish it, passing a unique_ptr<T> value is in place. Ther are as far as I can see three reasonable modes of passing such a value.
Passing by value, as in add(unique_ptr<B> b) in the question.
Passing by non-const lvalue reference, as in add(unique_ptr<B>& b)
Passing by rvalue reference, as in add(unique_ptr<B>&& b)
Passing by const lvalue reference would not be reasonable, since it does not allow the called function to take ownership (and const rvalue reference would be even more silly than that; I'm not even sure it is allowed).
As far as valid code goes, options 1 and 3 are almost equivalent: they force the caller to write an rvalue as argument to the call, possibly by wrapping a variable in a call to std::move (if the argument is already an rvalue, i.e., unnamed as in a cast from the result of new, this is not necessary). In option 2 however, passing an rvalue (possibly from std::move) is not allowed, and the function must be called with a named unique_ptr<T> variable (when passing a cast from new, one has to assign to a variable first).
When std::move is indeed used, the variable holding the unique_ptr<T> value in the caller is conceptually dereferenced (converted to rvalue, respectively cast to rvalue reference), and ownership is given up at this point. In option 1. the dereferencing is real, and the value is moved to a temporary that is passed to the called function (if the calles function would inspect the variable in the caller, it would find it hold a null pointer already). Ownership has been transferred, and there is no way the caller could decide to not accept it (doing nothing with the argument causes the pointed-to value to be destroyed at function exit; calling the release method on the argument would prevent this, but would just result in a memory leak). Surprisingly, options 2. and 3. are semantically equivalent during the function call, although they require different syntax for the caller. If the called function would pass the argument to another function taking an rvalue (such as the push_back method), std::move must be inserted in both cases, which will transfer ownership at that point. Should the called function forget to do anything with the argument, then the caller will find himself still owning the object if holding a name for it (as is obligatory in option 2); this in spite of that fact that in case 3, since the function prototype asked the caller to agree to the release of ownership (by either calling std::move or supplying a temporary). In summary the methods do
Forces caller to give up ownership, and be sure to actually claim it.
Force caller to possess ownership, and be prepared (by supplying a non const reference) to give it up; however this is not explicit (no call of std::move required or even allowed), nor is taking away ownership assured. I would consider this method rather unclear in its intention, unless it is explicitly intended that taking ownership or not is at discretion of the called function (some use can be imagined, but callers need to be aware)
Forces caller to explicitly indicate giving up ownership, as in 1. (but actual transfer of ownership is delayed until after the moment of function call).
Option 3 is fairly clear in its intention; provided ownership is actually taken, it is for me the best solution. It is slightly more efficient than 1 in that no pointer values are moved to temporaries (the calls to std::move are in fact just casts and cost nothing); this might be especially relevant if the pointer is handed through several intermediate functions before its contents is actually being moved.
Here is some code to experiment with.
class B
{
unsigned long val;
public:
B(const unsigned long& x) : val(x)
{ std::cout << "storing " << x << std::endl;}
~B() { std::cout << "dropping " << val << std::endl;}
};
typedef std::unique_ptr<B> B_ptr;
class A {
std::vector<B_ptr> vb;
public:
void add(B_ptr&& b)
{ vb.push_back(std::move(b)); } // or even better use emplace_back
};
void f() {
A a;
B_ptr b(new B(123)),c;
a.add(std::move(b));
std::cout << "---" <<std::endl;
a.add(B_ptr(new B(4567))); // unnamed argument does not need std::move
}
As written, output is
storing 123
---
storing 4567
dropping 123
dropping 4567
Note that values are destroyed in the ordered stored in the vector. Try changing the prototype of the method add (adapting other code if necessary to make it compile), and whether or not it actually passes on its argument b. Several permutations of the lines of output can be obtained.
Yes, this is how it should be done. You are explicitly transferring ownership from main to A. This is basically the same as your previous code, except it's more explicit and vastly more reliable.
So my simple question: is this the way to do it and in particular, is this "move(b)" the only way to do it? (I was thinking of rvalue references but I don't fully understand it so...)
And if you have a link with complete explanations of move semantics, unique_ptr... that I was not able to find, don't hesitate.
Shameless plug, search for the heading "Moving into members". It describes exactly your scenario.
Your code in main could be simplified a little, since C++14:
a.add( make_unique<B>() );
where you can put arguments for B's constructor inside the inner parentheses.
You could also consider a class member function that takes ownership of a raw pointer:
void take(B *ptr) { vb.emplace_back(ptr); }
and the corresponding code in main would be:
a.take( new B() );
Another option is to use perfect forwarding for adding vector members:
template<typename... Args>
void emplace(Args&&... args)
{
vb.emplace_back( std::make_unique<B>(std::forward<Args>(args)...) );
}
and the code in main:
a.emplace();
where, as before, you could put constructor arguments for B inside the parentheses.
Link to working example