C++: is return value a L-value? - c++

Consider this code:
struct foo
{
int a;
};
foo q() { foo f; f.a =4; return f;}
int main()
{
foo i;
i.a = 5;
q() = i;
}
No compiler complains about it, even Clang. Why q() = ... line is correct?

No, the return value of a function is an l-value if and only if it is a reference (C++03). (5.2.2 [expr.call] / 10)
If the type returned were a basic type then this would be a compile error. (5.17 [expr.ass] / 1)
The reason that this works is that you are allowed to call member functions (even non-const member functions) on r-values of class type and the assignment of foo is an implementation defined member function: foo& foo::operator=(const foo&). The restrictions for operators in clause 5 only apply to built-in operators, (5 [expr] / 3), if overload resolution selects an overloaded function call for an operator then the restrictions for that function call apply instead.
This is why it is sometimes recommended to return objects of class type as const objects (e.g. const foo q();), however this can have a negative impact in C++0x where it can inhibit move semantics from working as they should.

Because structs can be assigned to, and your q() returns a copy of struct foo so its assigning the returned struct to the value provided.
This doesn't really do anything in this case thought because the struct falls out of scope afterwards and you don't keep a reference to it in the first place so you couldn't do anything with it anyway (in this specific code).
This makes more sense (though still not really a "best practice")
struct foo
{
int a;
};
foo* q() { foo *f = new malloc(sizeof(foo)); f->a = 4; return f; }
int main()
{
foo i;
i.a = 5;
//sets the contents of the newly created foo
//to the contents of your i variable
(*(q())) = i;
}

One interesting application of this:
void f(const std::string& x);
std::string g() { return "<tag>"; }
...
f(g() += "</tag>");
Here, g() += modifies the temporary, which may be faster that creating an additional temporary with + because the heap allocated for g()'s return value may already have enough spare capacity to accommodate </tag>.
See it run at ideone.com with GCC / C++11.
Now, which computing novice said something about optimisations and evil...? ;-].

On top of other good answers, I'd like to point out that std::tie works on top of this mechanism for unpacking data from another function. See here. So it's not error-prone per se, just keep in mind that it could be a useful design pattern

Related

Is it possible to avoid a copy when returning an argument from a function?

Suppose I have value type with some in-place operation. For example, something like this:
using MyType = std::array<100, int>;
void Reverse(MyType &value) {
std::reverse(value.begin(), value.end());
}
(The type and operation can be more complicated, but the point is the operation works in-place and the type is trivially copyable and trivially destructible. Note that MyType is large enough to care about avoiding copies, but small enough that it probably doesn't make sense to allocate on the heap, and since it contains only primitives, it doesn't benefit from move semantics.)
I usually find it helpful to also define a helper function that doesn't change the value in-place, but returns a copy with the operation applied to it. Among other things, that enables code like this:
MyType value = Reversed(SomeFunction());
Considering that Reverse() operates in-place, it should be logically possible to calculate value without copying the result from SomeFunction(). How can I implement Reversed() to avoid unnecessary copies? I'm willing to define Reversed() as an inline function in a header if that's what's necessary to enable this optimization.
I can think of two ways to implement this:
inline MyType Reversed1(const MyType &value) {
MyType result = value;
Reverse(result);
return result;
}
This benefits from return-value optimization but only after the argument value has been copied to result.
inline MyType Reversed2(MyType value) {
Reverse(value);
return value;
}
This might require the caller to copy the argument, except if it's already an rvalue, but I don't think return-value optimization is enabled this way (or is it?) so there's a copy upon return.
Is there a way to implemented Reversed() that avoids copies, ideally in a way that it's guaranteed by recent C++ standards?
If you do want to reverse the string in-place so that the change to the string you send in as an argument is visible at the call site and you also want to return it by value, you have no option but to copy it. They are two separate instances.
One alternative: Return the input value by reference. It'll then reference the same object that you sent in to the function:
MyType& Reverse(MyType& value) { // doesn't work with r-values
std::reverse(std::begin(value), std::end(value));
return value;
}
MyType Reverse(MyType&& value) { // r-value, return a copy
std::reverse(std::begin(value), std::end(value));
return std::move(value); // moving doesn't really matter for ints
}
Another alternative: Create the object you return in-place. You'll then return a separate instance with RVO in effect. No moves or copies. It'll be a separate instance from the one you sent in to the function though.
MyType Reverse(const MyType& value) {
// Doesn't work with `std::array`s:
return {std::rbegin(value), std::rend(value)};
}
The second alternative would work if std::array could be constructed from iterators like most other containers, but they can't. One solution could be to create a helper to make sure RVO works:
using MyType = std::array<int, 26>;
namespace detail {
template<size_t... I>
constexpr MyType RevHelper(const MyType& value, std::index_sequence<I...>) {
// construct the array in reverse in-place:
return {value[sizeof...(I) - I - 1]...}; // RVO
}
} // namespace detail
constexpr MyType Reverse(const MyType& value) {
// get size() of array in a constexpr fashion:
constexpr size_t asize = std::tuple_size_v<MyType>;
// RVO:
return detail::RevHelper(value, std::make_index_sequence<asize>{});
}
Your last option is the way to go (except for the typo):
MyType Reversed2(MyType value)
{
Reverse(value);
return value;
}
[N]RVO doesn't apply to return result;, but at least it's implicitly moved, rather than copied.
You'll have either a copy + a move, or two moves, depending on the value category of the argument.
There is a trick. It is NOT pretty but it works.
Make Reversed accept not a T, but a function returning T. Call it like that:
MyType value = Reversed(SomeFunction); // note no `SomeFunction()`
Here is a full implementation of Reversed:
template <class Generator>
MyType Reversed(Generator&& g)
{
MyType t{g()};
reverse(t);
return t;
}
This produces no copies or moves. I checked.
If you feel particularly nasty, do this
#define Reversed(x) Reversed([](){return x;})
and go back to calling Reversed(SomeFunction()). Again, no copies or moves. Bonus points if you manage to squeeze it through a corporate code review.
You can use a helper method that turns your in-place operation into something that can work on Rvalues. When I tested this in GCC, it results in one move operation, but no copies. The pattern looks like this:
void Reversed(MyType & m);
MyType Reversed(MyType && m) {
Reversed(m);
return std::move(m);
}
Here is the full code I used to test whether this pattern results in copies or not:
#include <stdio.h>
#include <string.h>
#include <utility>
struct MyType {
int * contents;
MyType(int value0) {
contents = new int[42];
memset(contents, 0, sizeof(int) * 42);
contents[0] = value0;
printf("Created %p\n", this);
}
MyType(const MyType & other) {
contents = new int[42];
memcpy(contents, other.contents, sizeof(int) * 42);
printf("Copied from %p to %p\n", &other, this);
}
MyType(MyType && other) {
contents = other.contents;
other.contents = nullptr;
printf("Moved from %p to %p\n", &other, this);
}
~MyType() {
if (contents) { delete[] contents; }
}
};
void Reversed(MyType & m) {
for (int i = 0; i < 21; i++) {
std::swap(m.contents[i], m.contents[41 - i]);
}
}
MyType Reversed(MyType && m) {
Reversed(m);
return std::move(m);
}
MyType SomeFunction() {
return MyType(7);
}
int main() {
printf("In-place modification\n");
MyType x = SomeFunction();
Reversed(x);
printf("%d\n", x.contents[41]);
printf("RValue modification\n");
MyType y = Reversed(SomeFunction());
printf("%d\n", y.contents[41]);
}
I'm not sure if this lack of copies is guaranteed by the standard, but I would think so, because there are some objects that are not copyable.
Note: The original question was just about how to avoid copies, but I'm afraid the goalposts are changing and now we are trying to avoid both copies and moves. The Rvalue function I present does seem to perform one move operation. However, if we cannot eliminate the move operation, I would suggest that the OP redesign their class so that moves are cheap, or just give up on the idea of this shorter syntax.
When you write
MyType value = Reversed(SomeFunction());
I see 2 things happen: Reversed will do RVO so it directly writes to value and SomeFunction either gets coppied into the argument for Reversed or creates a temporary object and you pass a reference. No matter how you write it there will be at least 2 objects and you have to reverse from one to the other.
There is no way for the compiler to do what I would call an AVO, argument value optimization. You want the argument to the Reversed function to be stored in the return value of the function so you can do in-place operations. With that feature the compiler could do RVO-AVO-RVO and SomeFunction would create it's return value directly in the final value variable.
But you could do this I think:
MyType &&value = SomeFunctio();
reverse(value);
Looking at it another way: Say you do figure out a way for Reveresed to do in-place operations then in
MyType &&value = Reversed(SomeFunction());
the SomeFunction would create a temporary but then the compiler has to extend the lifetime of that temporary to the lifetime of value. This works in direct assignment but how is the compiler supposed to know that Reversed will just pass the temporary through?
From the answers and comments it looks like the consensus is that there is no way to achieve this in C++.
It makes sense that this is the general answer without the implementation of MyType Reversed(MyType) available, since the compiler would have no clue that the return value is the same as the argument, so it would necessarily allocate separate spaces for them.
But it looks like even with the implementation of Reversed() available, neither GCC nor Clang will optimize away the copy: https://godbolt.org/z/KW6Y3vsdf
So I think the short story is that what I was asking for isn't possible. If it's important to avoid the copy, the caller should explicitly write:
MyType value = SomeFunction();
Reverse(value);
// etc.

Is it legal to cast const away of a non-static const field with guaranteed non const allocation

I have the following code which seems to work always (msvc, gcc and clang).
But I'm not sure if it is really legal. In my framework my classes may have "two constructors" - one normal C++ constructor which does simple member initialization and an additional member function "Ctor" which executes additional initialization code. It is used to allow for example calls to virtual functions. These calls are handled by a generic allocation/construction function - something like "make_shared".
The code:
#include <iostream>
class Foo
{
public:
constexpr Foo() : someConstField(){}
public:
inline void Ctor(int i)
{
//use Ctor as real constructor to allow for example calls to virtual functions
const_cast<int&>(this->someConstField) = i;
}
public:
const int someConstField;
};
int main()
{
//done by a generic allocation function
Foo f;
f.Ctor(12); //after this call someConstField is really const!
//
std::cout << f.someConstField;
}
Modifying const memory is undefined behaviour. Here that int has already been allocated in const memory by the default constructor.
Honestly I am not sure why you want to do this in the first place. If you want to be able to initalise Foo with an int just create an overloaded constructor:
...
constexpr Foo(int i) : someConstField{i} {}
This is completely legal, you are initalising the const memory when it is created and all is good.
If for some reason you want to have your object initalised in two stages (which without a factory function is not a good idea) then you cannot, and should not, use a const member variable. After all, if it could change after the object was created then it would no longer be const.
As a general rule of thumb you shouldn't have const member variables since it causes lots of problems with, for example, moving an object.
When I say "const memory" here, what I mean is const qualified memory by the rules of the language. So while the memory itself may or may not be writable at the machine level, it really doesn't matter since the compiler will do whatever it likes (generally it just ignores any writes to that memory but this is UB so it could do literally anything).
No.
It is undefined behaviour to modify a const value. The const_cast itself is fine, it's the modification that's the problem.
According to 7.1.6.1 in C++17 standard
Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const
object during its lifetime (3.8) results in undefined behavior.
And there is an example (similar to yours, except not for class member):
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
If your allocation function allocates raw memory, you can use placement new to construct an object at that memory location. With this you must remember to call the destructor of the object before freeing the allocation.
Small example using malloc:
class Foo
{
public:
constexpr Foo(int i) : someConstField(i){}
public:
const int someConstField;
};
int main()
{
void *raw_memory = std::malloc(sizeof(Foo));
Foo *foo = new (raw_memory) Foo{3}; // foo->someConstField == 3
// ...
foo->~Foo();
std::free(foo);
}
I suggest, that you use the constructor to avoid the const cast. You commented, that after your call of Ctor the value of someConstField will remain const. Just set it in the constructor and you will have no problems and your code becomes more readable.
#include <iostream>
class Foo
{
public:
constexpr Foo(int i) : someConstField(Ctor(i)){}
int Ctor(); // to be defined in the implementation
const int someConstField;
};
int main()
{
Foo f(12);
std::cout << f.someConstField;
}

volatile struct = struct not possible, why?

struct FOO{
int a;
int b;
int c;
};
volatile struct FOO foo;
int main(void)
{
foo.a = 10;
foo.b = 10;
foo.c = 10;
struct FOO test = foo;
return 0;
}
This won't compile, because
struct FOO test = foo;
generates an error:
error: binding reference of type 'const FOO&' to 'volatile FOO'
discards qualifiers
How can I copy a volatile struct into another struct in C++ (before C++11)?
Many people suggested to just delelte volatile, but I can't do that in that case, because I want to copy the current SPI-Reg setttings inside a µC and this is declared volatile by the manufacturer headers.
I want to copy those settings, because the manufactuerer also provides an Library to use the SPI for EnDat-Communication, and I don't have access to the source-code. Since I have to change the SPI-Reg-Settings during runtime I want to easyly get back to the library SPI-settings without calling the init_endat()-lib fkt again (it's unspecified what happens if i call it twice).
Could I possibly use memcopy() for that?
As suggested, this is a copy of the following question.
Why am I not provided with a default copy constructor from a volatile?
This is ill-formed because FOO has an implicit copy constructor defined as:
FOO(FOO const&);
And you write FOO test = foo; with foo of type volatile FOO, invoking:
FOO(volatile FOO const&);
But references-to-volatile to references-to-non-volatile implicit conversion is ill-formed.
From here, two solutions emerge:
don't make volatile to non-volatile conversions;
define a suited copy constructor or copy the object members "manually";
const_cast can remove the volatile qualifier, but this is undefined behavior to use that if your underlying object is effectively volatile.
Could I possibly use memcopy() for that?
No you cannot, memcpy is incompatible with volatile objects: thre is no overload of it which takes pointers-to-volatile, and there is nothing you can do without invoking undefined behavior.
So, as a conclusion, your best shot if you cannot add a constructor to FOO is to define:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
result.a = other.a;
result.b = other.b;
result.c = other.c;
return result;
}
Or with C++11's std::tie:
FOO FOO_copy(FOO volatile const& other)
{
FOO result;
std::tie(result.a, result.b, result.c) = std::tie(other.a, other.b, other.c);
return result;
}
To give another approach to an answer, to address why this doesn't make sense, rather than just where the C++ standard says this is invalid:
The whole point of volatile is that you have precise control over which variable gets accessed when. That means given volatile int i, j;, i = 1; j = 2; and j = 2; i = 1; do not do the same thing. The compiler cannot freely transform one into the other. The same applies to reads: given volatile int i, j; int x, y;, x = i; y = j; and y = j; x = i; do not do the same thing. The presence of volatile means the accesses must happen in exactly the order you specified.
Now, in your example, what should struct FOO test = foo; do? You've never specified whether you want to first read foo.a, then foo.b, finally foo.c, or perhaps first read foo.c, then foo.b, finally foo.a, or perhaps some other order.
You can, if you wish, do this:
struct FOO test;
test.a = foo.a;
test.b = foo.b;
test.c = foo.c;
Here, you explicitly specify the order of the accesses to foo's fields, so you avoid the problem.
You haven't provided enough details about your problem to give a more precise assessment, but the solution to whatever problem you're trying to solve is almost certainly not to use volatile. "Volatile" means that the value can change from under your feet: the two typical good use cases are variables changed from within UNIX signal handlers and memory-mapped registers. Volatile is not enough for variables shared among threads, notably.
The reason you are getting this error is that your compiler is trying to find a FOO(volatile FOO&) copy constructor, which is never automatically generated.

About using returned references

I'm having some trouble trying to understand proper usage of returned references in C++.
I have a class with a "big" object inside. I want to be able to use this object outside the class "read only" mode by returning a const reference to it.
The problem is I don't quite understand when objects get copied and when they don't.
Most of the questions about returning references where about returning objects allocating on the stack, which is not my particular problem, so I've prepared this little example:
class foo {
int a;
public:
foo() {
a = 3;
}
int& getInt() {
return a;
}
const int& useInt() {
return a;
}
void print() {
cout << "Inside class: a = " << a << endl;
}
};
int main() {
foo foo1;
int& goodRef = foo1.getInt();
int badRef = foo1.getInt();
goodRef = 4;
badRef = 5;
foo1.print();
foo1.getInt() = 6;
foo1.print();
int usingIt = 10*foo1.useInt();
}
What I understand is:
In int& goodRef = foo1.getInt(); nothing is copied, only the class owned a exists.
In int badRef = foo1.getInt(); badRef is a copy of a, so there are 2 separate objects, a and badRef.
So depending on what type of object catches the return value it is copied or it is not, so my question is:
When I use the reference like in int usingIt = 10*foo1.useInt(); is it copied and then used to multiply or only the value inside the class is used?
In this example it doesn't matter since it is only an int, but if it was a big object it would be a big deal.
Thanks!
Edit: Thanks to all the answers, but I get that having such methods inside a class is bad, I only put them for the sake of the example.
My actual class has a bunch of objects inside and an interface and bla bla, but one particular object is a glm::mat4. What i want is to be able to write something like glm::vec4 finalVec = foo1.getMatrix() * vec. But I dont want the whole matrix to be copied and then multiplied, rather I want to use the matrix that is already inside my class to perform the multiplication and at the same time not let the user modify it. I supposed something similar to useInt but with the mat4 would work but I wasn't sure and that's why I asked the question.
The glm specificatioon is very confuse for me, but I think the operator * is described as:
glm::mat4 operator* (glm::mat4 const & m, glm::vec4 const & v);
In your example int usingIt = 10*foo1.useInt();, the operator*(), depending on it's argument signature and internals, could cause a copy of your object to take place, at which point it would then be assigned (rather than copied again) into the value of usingIt. If your object was an aggregate or class object type, the copy using the object type's assignment operator would typically be elided using a compiler optimization step.
In general, anytime you are copying a l-value reference type (i.e., T& or const T&) to an aggregate or class object to a non-reference type (i.e., type T), a copy constructor, constructor, assignment operator, or conversion operator is invoked on the returned reference to the object.
If getInt returns int& why are you catching the return value in an int? What do you expect, that the compiler changes your source code to use a reference to int? It can't do anything else than copying the value of the object pointed by the reference.
On the other hand I think you have a bad example. Either you define a single method that returns a const reference:
int const & getInt() { return a; }
Or you provide two methods, one const and one non const:
int& getInt() { return a; }
int const & getInt() const { return a; }
Having both getInt and useInt does not stop anyone from using getInt and actually changing the value of the object in an way that is not intended.
When you use const reference you can only use const methods of this object. E.g. when you have STL vector you can get size, but you can't push_back elements to it.
vector<int> a;
vector<int> &c = a;
const vector<int> &b = a;
a.size();
b.size();
a.push_back(4);
c.push_back(4);
//our vector is now 4 4
//b.push_back(4); compilation error
In C++ you copy when you want to copy: for example
Function which copies:
int x(vector<int> b)
Function which doesn't copy:
int x(vector<int> &b)
You can read more here

How to default-initialize local variables of built-in types in C++?

How do I default-initialize a local variable of primitive type in C++? For example if a have a typedef:
typedef unsigned char boolean;//that's Microsoft RPC runtime typedef
I'd like to change the following line:
boolean variable = 0; //initialize to some value to ensure reproduceable behavior
retrieveValue( &variable ); // do actual job
into something that would automagically default-initialize the variable - I don't need to assign a specific value to it, but instead I only need it to be intialized to the same value each time the program runs - the same stuff as with a constructor initializer list where I can have:
struct Struct {
int Value;
Struct() : Value() {}
};
and the Struct::Value will be default-initialized to the same value every time an instance is cinstructed, but I never write the actual value in the code.
How can I get the same behavior for local variables?
You can emulate that behaviour by the following:
boolean x = boolean();
or, more general,
T x = T();
This will default-initialize x if such a default-initialization exists. However, just writing T x will never do the trick for local variables, no matter what you do.
You can also use placement-new to invoke a “constructor”, even for POD:
T x;
new (&x) T();
Notice that this code produces undefined behaviour for non-POD types (in particular for types that have a non-trivial destructor). To make this code work with user-defined types, we first need to call the object’s destructor:
T x;
x.~T();
new (&x) T();
This syntax can also be used for PODs (guaranteed by §§5.2.4/12.4.15) so the above code can be used indiscriminately for any type.
int var = int();
string str = string();
...
...or whatever typename you want.
You could provide a wrapper that behaves as the underlying type through overloaded conversion operators.
#include <cassert>
template <class T>
class Type
{
T t;
public:
Type(const T& t = T()): t(t) {}
operator T&() { return t; }
operator const T&() const { return t; }
};
int main()
{
Type<unsigned char> some_value;
assert(some_value == '\0');
}
This should be a rather OK usage for conversion operators.
Wrapping in the struct (Boolean) as in your example and accessing via a public member (Boolean::value). It may not be the most elegant solution (some cruft for small benefit), but it similar to what you already showed.
If I understand the original question, the poster is saying he wants variables of a given type to always have the same initial value, but he doesn't care what that value is, because he'll never look at it. Am I right?
If so, then my question for the poster is this: If you did not initialize the variables they would have random initial values... but you said you never look at initial values - so why does it matter if they're random?
I think the key question is - what are you trying to achieve here?