Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Is the following code safe?
struct Foo {
Foo bar() { return *this; }
} foo;
foo = std::move(foo).bar(); // is this safe?
I'm wondering if calling methods on an rvalue is safe.
In general, calling a function on an rvalue is no more or less safe than calling it on an lvalue.
As for your specific code, no movement actually happens. std::move(foo) converts it into an rvalue, which is irrelevant to the call to Foo::bar since it doesn't care whether this is an lvalue or an rvalue. bar will return a copy of foo, which will then be copied back into foo.
The same thing would have happened if you hadn't used std::move at all. std::move doesn't actually move anything; it simply converts it into an rvalue which can participate in a move operation.
Your real question is this: for any type T which is moveable, is this legal:
T t;
t = T(std::move(t));
The answer is... maybe. The state of a moved-from object is exactly what the writer of T chooses for it to be. For most standard library types, it will be "valid-but-unspecified". This means that you can use functions that don't require preconditions, that will work regardless of the current state.
Move assignment is usually such a function, so that will generally work. Will it work for all types? There is nothing which guarantees that it will. It depends on how move support is implemented for each type. Some user-defined types can't achieve even a "valid-but-unspecified" state, which means the only thing you're allowed to do with a moved-from object is destroy it.
It all depends on how users choose to work. However, I would say that a type for which t = T(std::move(t)) does not work (that is, yields undefined behavior) would be a very ill-behaved type.
Not super safe, it is sometimes hard to break down, if it's just for a simple program/game it should be fine, I would recommend that you use a more secure code for a big program :)
Overall it's not going to be too bad if it breaks.
What I mean by super safe is that it can't handle a break, if you decide to use a function of a standard way of doing it (e.g: using Struct like you have)
Sorry I can't supply as much information as I can, I'm newish to struct
if anyone wants to edit my answer they can.
Thanks,
~Coolq
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
So there are copy semantics, move semantics and maybe more semantics that I don't know of. I have read articles about both but I still do not really get have a good definition of "semantics". As the name suggests, move semantics have something to do with moving things but why is it called move semantics?
The more clear version: What is the meaning of semantics in the context of programming? Example: Move and copy semantics.
Semantics basically means "the meaning of".
It may help to look at a more familiar case to explain the term.
Consider:
int a = 3;
int b = 5;
int c = a + b;
The value of a + b is 8 because the semantics of the + operator is to take the numerical sum of its operands.
Now consider this:
std::string a = "hello";
std::string b = "world";
std::string c = a + b;
The value of a + b is "helloworld" because the semantics of the + operator is to concatenate its operands.
The + operator, when used with std::string is said to have different semantics from when it is used with numerical types.
It has a different meaning.
Now consider copy and move semantics:
std::string a = "hello";
std::string b;
b = a; // b receives a copy of a's value
b = std::string("hello"); // the temporary value is moved into b
We have the same operator = which has a different meaning in different situations. Again we say is has different semantics.
The first case has copy semantics and the second case has move semantics.
The word semantics is used to describe an underlying meaning of something.
You can say that an operation has the move semantics when it transfers an object state from one object to another. In reality of course what happens is some pointers are probably copied over and that's it, but semantically your object has been moved.
Another example is the ownership transfer, when the most important thing that is moved is the responsibility (i.e. the promise to release some resource). In that case from the computational point of view pretty much nothing happens, but semantically the ownership is transferred.
The same goes for copy semantics: you can say that passing an object to a function has copy semantics i.e. your object would be duplicated and the function will get a standalone copy with its own lifetime.
Another side of the coin is the syntax which is how you describe what you want following the rules of the language.
C++ has really flexible syntax - overloading operators, user-defined conversions, macros and what not, so almost any desirable semantics can be attached to any particular syntax.
Semantics is about the meaning of something. move-semantic is about the meaning of moving objects. Specifically, in this context, it tells you what it means to move something in C++.
The semantic of moving is all about everything that is involved during a move operation.
read move-semantic as: what does it mean, what are the implications (and how do you achieve it ) of moving an object in a C++ program?
The following is a good answer that might help: What are move semantics?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
Everytime I think about the design of my class I ask myself these questions, should I use the pass by value, should I overload on const lvalue reference and rvalue reference or should I use perfect forwarding.
Often I use pass by value as having cheap to move types and I almost never use perfect forwarding. I overload when having only 1 parameter, maybe 2 if i really need the perf.
What do you do ?
Do you have easy rules of thumb to decide how to pass arguments, for member/non member functions but also for constructors and all the copy/assignment guys.
Thanks.
So all of the following is opinion-based, but these are the rules I tend to follow when thinking about an API. As always in C++, there are many ways to accomplish the same thing, and people will have different view on exactly what is best.
There are three kinds of parameters we need to think about: in parameters, out parameters, and in/out parameters. The latter two are simple, so we'll cover them first.
Out parameters
Don't use them. Seriously. If your function is going to return a new object, then return it by value. If you're going to return multiple new objects, then return them by value packed in a std::tuple (or std::pair). The caller can use std::tie (or structured bindings in C++17) to unpack them again. This gives the caller the maximum flexibility, and with RVO it's no less efficient than any other method.
In/out parameters
For functions which modify an already-constructed value, use a mutable lvalue reference, i.e. T&. This will prevent callers from passing a temporary, but that's actually a good thing: what would be the point of modifying something you're just going to throw away? Not that some style guides (notably Google's, but also Qt) advocate using a raw pointer (T*) in this situation, so that it's obvious at the call site that the argument will be modified (because you need to say f(&arg)), but I personally don't find this convincing.
In parameters
For pure input parameters, where the function will not modify the argument passed to it, things are a tiny bit more complicated. In general, the best advice is to pass by lvalue-reference-to-const, that is, const T&. This will allow the caller to pass both lvalues and rvalues. However, for small objects (sizeof(T) <= sizeof(void*)), such as int, it can be more efficient to pass by value instead.
An exception though is if you're going to take a copy of a passed argument, for example in a constructor; in this case, it's better to take the parameter by value, because the compiler can turn this into a move for rvalues.
What about T&&?
There are two circumstances where it's appropriate to use arguments of the form T&&. The first is templated forwarding functions where the type of the parameter is the template type, i.e.
template <typename T>
decltype(auto) func(T&& arg) {
return other_func(std::forward<T>(arg));
}
In this case, although the parameter looks as if it's an rvalue reference, it's actually a forwarding reference (sometimes called a universal reference). Only use a forwarding reference to pass things on to another function via std::forward; if you care about the value category of the argument, then T&& is not appropriate.
The second case is for real rvalue references, where the argument type is not a template parameter. In a very limited number of cases, it can be appropriate to overload on both the const arg& and arg&& forms, to avoid an unnecessary move. This should only be necessary in performance-critical situations in which you're going to copy or move the argument somewhere (for example, std::vector does this for its push_back() method) -- in general I would say it's better to take the argument by value and then move it into place.
Interfaces should express intent.
Optimisations should happen when users complain.
To me, the following interfaces have different meanings:
void foo(thing const& t); // "I won't modify your t. If it's copyable, I might copy it, but that's none of your concern."
void foo(thing t); // "Pass me a copy if you wish, or a temporary, or move your thing into me. What I do with t is up to me".
void foo(thing& t); // "t will be modified."
What follows now is only for "default" behavior. Like "normal" not really big types ("normal sized" vectors, strings etc.) nothing which seems to be very expensive in the first place.
In short:
Do whatever you like but be consistent.
There is no best practice which can guarantee you the best performance.
Some detail to this:
I was once on a conference having 3 popular C++ people (Herb Sutter, Andrei Alexandrescu and Scott Meyers) discuss this problem and each had another opinion on the best "default" behavior.
All by const-reference or by perfect-forwarding or just by-value.
So you won't get a perfect answer here. Compilers also can optimize differently etc.
Here is my personal opinion on this:
What I do is I prefer the by-value approach and if I later notice some thing becoming slow I start to optimize. I assume modern compilers being smart enough to avoid unnecessary copies and also maybe just move the object when they see it's no longer used afterwards. I try to keep in mind Return Value Optimization to let the compiler more easier optimize here if necessary (either return only one object or only r-values).
Though I have heard this behavior and optimization potential changing from compiler to compiler. So like said before: use what you prefer / stick to one way so it's consistent.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
When I was learning C++, I was told that if you want to have multiple classes reference the same object, you should give both a pointer to the object. In Modern C++, I'd probably interpret this as the object being a unique_ptr and the classes holding non-owning-raw-pointers.
Recently, my mentor at work suggested that you should only use pointers when you plan on having the store point to a different object or null at some point. Instead, you should store references in classes.
Reference member variables are a thing I've actually never seen before, so I was looking for advice on what the concerns were... It makes sense... You're saying that this reference is assumed to never be null... I guess the concern would then be that you couldn't /check/ for null. It would have to be an invariant of your class...
How about how this applies to using the references for polymorphism?
Update:
The answer that I selected covers my questions pretty well, but I thought I'd clarify for future readers. What I was really looking for was an idea of the consequences of using a reference rather than a pointer as a class member. I realise that the way the question was phrased made it sound more like I was looking for opinions on the idea.
Should I store references in classes in c++?
yes, why not. This question is IMO 'primarily opinion-based', so my answer is based on my own experience.
I use member references when I dont need what pointers have to offer, this way I limit possiblity that my class will be wrongly used. This means among other possibility to bind new value, assign nullptr, you cant take pointer to reference, you cannot use reference arithmetics - those features are missing in references. You should also remember that reference is not an object type, this means among others that if you put a reference as struct member, then it is no longer POD - i.e. you cannot use memcpy on it.
You should also remember that for classes which have non static reference member, compiler will not generate implicit constuctors.
For me this means references as variable members are mostly usefull when class is some kind of wrapper, or a holder. Below is an example which also shows an alternative implementation using pointer member type. This alternative implementation gives you no additional benefit to the reference one, and only makes it possible to introduce Undefined Behaviour.
struct auto_set_false {
bool& var;
auto_set_false(bool& v) : var(v) {}
~auto_set_false() { var = false; }
};
struct auto_set_false_ptr {
bool* var;
auto_set_false_ptr(bool* v) : var(v) {}
~auto_set_false_ptr() { *var = false; }
};
int main()
{
// Here auto_set_false looks quite safe, asf instance will always be
// able to safely set nval to false. Its harder (but not imposible) to
// produce code that would cause Undefined Bahaviour.
bool nval = false;
auto_set_false asf(nval);
bool* nval2 = new bool(true);
auto_set_false_ptr asf2(nval2);
// lots of code etc. and somewhere in this code a statement like:
delete nval2;
// UB
}
It is generally not a good idea to store references in a class because the class cannot be default constructed, copy assigned, move assigned, and the member cannot be changed (the reference cannot be rebound).
That renders the class uncopieable. It therefore cannot be copied, moved or placed in most containers. The far more flexible and less surprising solution is to store a pointer or a std::refernce_wrapper.
IMO references works like pointers.
The only difference is in dynamic_cast: a failed cast produces a nullpointer with pointers, and results in a throw an exception with references.
References are far better than pointers because of one reason: you don't have to play with nulls.
A reference can't be null and it is a big value to not have to check for nulls.
The small difficulty is that you have to assign reference member in a constructor.
But you can definitely change it later to other non-null value pointing to an object of a class of the member or subclass of this class.
So it supports inheritance like pointers do.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I've noticed this weird behaviour/bug where a class method is called before the actual object is initialized. I have a wrapper object, which has operator->() method. Now, when I'm passing the object to another object as constructor parameter in a constructor using the operator->() method, the actual wrapper object doesn't get constructed, but rather just runs the operator->() method.
As the actual code sample is pretty complicated and depends on many other things, I'll just show C++ code snippet which may not compile properly:
template<typename T>
class wrapper_object_type
{
public:
wrapper_object_type() {/*does not run*/}
T* operator->() {/*does run*/}
};
class bad_behaviour
{
public:
bad_behaviour() : another_object(wrapper_object->t_object)
{/*crashes(0xccc access violation*/}
};
So is there something defined in the standard that may allow such behaviour? Or more accurately, are there some implicit constructions etc. which could bypass the default construction?
Probably you use wrapper_object before it gets initialized. Member variables are constructed in the same order in which they are declared in the class, so make sure wrapper_object is declared before another_object.
(Assuming wrapper_object and another_object are members variables of bad_behaviour, but without a more reasonable code sample it's hard to say.)
Well I did it the hardway; I switched the objects from stack to heap and initialized them explicitly via new keyword rather than in initializer list. As I thought, that didn't reproduce the weird behaviour, so it worked as intended. What I'm thinking now, is that it may be actually a compiler bug, since the way I did it via initializer list is analog to how I fixed the problem. Only thing that changed was the fact that I didn't allocate them in heap before.
I also tried to provide working code which reproduces the bug, but the bug wasn't shown there. It may be because the actual code where the bug was noticed, relies quite heavily to template types and wrapper objects. As it works now when the objects are allocated in heap, the bug isn't in the code but rather in the compiler.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
The community reviewed whether to reopen this question 8 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I was coding up a C++ class today, and I wrote a function that took an argument as a reference rather than a pointer, something I rarely ever do. I've always passed by pointers. So I was about to change it back, and then I realized - I have no idea if I should, or if it even matters.
So I turn to you guys. I have three ways of passing parameters about:
//1: By pointer
Object* foo(Object* bar) {…}
//2: By reference
Object& foo(Object& bar) {…}
//3: By value (just for completeness)
Object foo(Object bar) {…}
Assuming #3's out for performance reasons (yes, I know compilers have gotten pretty good at this, but still), the other two are more or less equivalent.
So: What's the "best" method? Pointers? References? Some combination of the two? Or does it even matter? Technical reasons are the best, but stylistic reasons are just as good.
Update: I've accepted YeenFei's answer, since it deals with the difference that clinched it for me (even if I then pointedly ignored his advice - I like having NULL as an option...). But everyone made good points - especially GMan (in the comments), and Nemo, in the answer dealing with performance and passing by value. If you're here for answers, check them all!
I would suggest to pass your argument by reference if it is expected to be valid. This would be a by-design optimization and save you from defensive programming.
Reference cannot be null while pointer can.
If you are dealing with pointer, you will need to verify whether given pointer is valid (non-null) regardless it is in raw form or wrapped in managed container (shared_ptr), before using them.
So I am going to make the case for choice #3. Consider the following code:
struct Foo {
int x;
int y;
};
Foo
add(Foo a, Foo b)
{
Foo result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
Foo
add2(Foo &a, Foo &b)
{
Foo result;
result.x = a.x + b.x;
result.y = a.y + b.y;
return result;
}
Try examining the generated assembly. Notice how add is almost entirely register operations, nicely scheduled. Notice how add2 is lots of memory accesses without any reordering.
I wrote a main that called each of these functions 10 billion times. Result? add took 22 seconds, while add2 took 26 seconds. Even for this trivial example, that's 10-20% better performance for the pass-by-value version.
OK, so the structure is trivial. But so is the function. The more complex the function, the more likely the pass-by-value version is to be faster, because the compiler knows that the two arguments do not "overlap". This is a huge benefit to optimization.
Of course, this decision should primarily be based on the semantics of the function: Do you need NULL to be a legal value? If so, obviously you need a pointer. Do you need to modify the objects? Then use a pointer or a reference.
But if you do not need to modify the objects, prefer to pass them by value unless the objects are large and/or have a non-trivial copy constructor (e.g. std::string). If by-value really is too slow, pass by reference-of-const or pointer-to-const.
But do not underestimate the potential speed advantages of passing by value, which derive from the advantages of registers vs. memory and instruction reordering. And note that these advantages become more pronounced with every generation of CPU.
Passing by pointer and by reference are really the same, except in syntax. I prefer passing by pointer, because it makes things explicit:
Object bar;
ptr_foo(&bar); // bar may change
ref_foo(bar); // can bar change? Now I need to go look at the prototype...
val_foo(bar); // bar cannot change. (Unless you use references here and there)
The only technical preference between passing values and pointers, as you have touched on is if the class is large enough to make its passing slow.
References any day, if you're designing everything yourself. Idiomatic modern C++ should almost never have raw pointers sticking out anywhere. Dynamically allocated objects should travel in resource managing containers (shared_ptr or unique_ptr, or weak_ptr if applicable), but for most operations passing by (const) reference is the primary way to pass arguments that need to be modified or that are of a heavy-weight type. Don't forget that passing by value may be a viable option if you have movable types.
Use:
const reference if the object is not modified
pointer if the object is modified or can be null
value if the object is small and you care about performance or if you need a copy of the object inside the function. This allows the compiler to pick the best way to copy/move the argument.
std::unique_ptr if ownership is transferred to the function.
You can take a look at https://www.boost.org/doc/libs/1_51_0/libs/utility/call_traits.htm library, it converts the type to the best arguments type automatically.