I'm currently in a C++ Course and im struggling with References. I know there are some similar topics, but i couldnt find an answer for this.
The thing is my Prof wants us to use References when returning objects, so return by value or using a pointer as return is no option.
So i guess i have to use a dynamic allocated object (returning a reference to a local object ends in a mess...right?)
1. Complex& method() {
2. Complex *object = new Complex();
3. return *object; }
Here is where im struggling, how do i catch the return right?
1. Complex one = object.method();
As far as i understand, with this i will get only a Copy and a Memory Leak
So how do i catch it with a pointer?
1. Complex *two = new Complex();
2. delete two;
3. *two = object.method();
this seems to work, but is there a way of it in just one line? Or should it be done different?
One idea is to store the returned object inside your object:
class Obj {
public:
Complex &method() { c.data = 10; return c; }
private:
Complex c;
};
This way there isn't any returning of local variable, or heap allocation.
returning a reference is efficient when you returning class member,
like:
class A{
Complex member;
public:
Complex& method(){
return member;
}
};
You also can return reference in manner to return some static or global object that can't be NULL, like:
Complex& method() {
static Complex c; // c cant be null
return c;
}
the advantage of using reference is that you can use the function call as an object, like: cin>>method().real>>method().img; and use the same object even if you call the method several times.
But your code doesn't feet to use reference, because each call creates a new instance.
if you are using dynamic allocation you should return a pointer:
Complex* method() {
return new Complex();
}
and you should remember to delete it.
my Prof wants us to use References when returning objects
When I read this, my first thought was that your professor meant:
void method(Complex& nonConstPassByReference)
{
nonConstPassByReference.data = 10;
}
or
int method(Complex& nonConstPassByReference)
{
nonConstPassByReference.data = 10;
return (0); // no error occurred
}
And when I use this technique, I now use
std::string method(Complex& nonConstPassByReference)
{
std::stringstream ss;
nonConstPassByReference.data = 10;
// more stuff
if (anErrorOccurred)
ss << errorDescriptionInfo << std::endl;
return (ss.str()); // no error occurred when return size is 0
}
This comes from the idea that, in general, all methods or functions can have two kinds of formal parameters. We call them pass-by-value, and pass-by-reference.
In general, all functions / methods can have both input and output formal parameters. And usually, input parameters are pass-by-value. Output parameters are non-const-pass-by-reference, inviting the method body to send its results back to the prebuilt instance of the calling code.
Occasionally, pass-by-reference variables are used for 'input-to-method' parameters (perhaps for performance - to avoid an expensive copy). In this case, the input-to-method-pass-by-reference parameters should be marked with 'const', to ask the compiler to generate an error if the code tries to modify that input.
Note that many C functions do NOT return a value which is part of the action ... return is instead an 'error occurred' indication, with the error description stashed in errno.
Related
It's my first year of using C++ and learning on the way. I'm currently reading up on Return Value Optimizations (I use C++11 btw). E.g. here https://en.wikipedia.org/wiki/Return_value_optimization, and immediately these beginner examples with primitive types spring to mind:
int& func1()
{
int i = 1;
return i;
}
//error, 'i' was declared with automatic storage (in practice on the stack(?))
//and is undefined by the time function returns
...and this one:
int func1()
{
int i = 1;
return i;
}
//perfectly fine, 'i' is copied... (to previous stack frame... right?)
Now, I get to this and try to understand it in the light of the other two:
Simpleclass func1()
{
return Simpleclass();
}
What actually happens here? I know most compilers will optimise this, what I am asking is not 'if' but:
how the optimisation works (the accepted response)
does it interfere with storage duration: stack/heap (Old: Is it basically random whether I've copied from stack or created on heap and moved (passed the reference)? Does it depend on created object size?)
is it not better to use, say, explicit std::move?
You won't see any effect of RVO when returning ints.
However, when returning large objects like this:
struct Huge { ... };
Huge makeHuge() {
Huge h { x, y, x };
h.doSomething();
return h;
}
The following code...
auto h = makeHuge();
... after RVO would be implemented something like this (pseudo code) ...
h_storage = allocate_from_stack(sizeof(Huge));
makeHuge(addressof(h_storage));
auto& h = *properly_aligned(h_storage);
... and makeHuge would compile to something like this...
void makeHuge(Huge* h_storage) // in fact this address can be
// inferred from the stack pointer
// (or just 'known' when inlining).
{
phuge = operator (h_storage) new Huge(x, y, z);
phuge->doSomething();
}
I am going over a mock exam in revision for my test, and one question on the paper confuses me.
Q.)An application is required to pass a structure to a function, which will modify the contents of the structure such that on return from the function call the caller can use the new structure values. Would you pass the structure to the function by value, address or reference?
State clearly why you chose a particular method. Justify your choice by comparing the three methods.
Now I have difficulty understanding this, because I assume the best answer to the question would always be by Ref as that takes the reference pointer of the value and edits its contents rather than just getting a copy. This would be different if using a class based program.
The only other method I would understand would be having a separate value and getting and setting the values, but this would mean extra lines of code, I am a little unsure on what this means, can anyone help enlighten me ? I do not know any other methods to achieve this.
This is not "advanced programming"; it is the absolute basics of C++.
Whether return-by-value or "out" parameters (implementing using references or pointers) are "best" for any given use case depends on a number of factors, style and opinion being but two of them.
// Return by value
// T a; a = foo(a);
T foo(const T& in) // or: T foo(T in)
{ // {
T out = in; //
out.x = y; // in.x = y;
return out; // return in;
} // }
// Out parameter (reference)
// T a; foo(a);
void bar(T& in)
{
in.x = y;
}
// Out parameter (pointer)
// T a; foo(&a);
void baz(T* in)
{
in->x = y;
}
The question is asking you what the pros and cons are of these three approaches.
How do I return a parameter from a method, unchanged, and without a copy in c++?
// This is more or less the desired signature from the caller's point of view
SomeImmutableObject ManipulateIfNecessary(SomeImmutableObject const& existingObject)
{
// Do some work…
// ...
if (manipulationIsNeccessary)
{
// Return a new object with new data etc (preferably without another copy)...
return SomeImmutableObject(...);
}
else
{
// Return the original object intact (but with no further copies!)...
return existingObject;
}
}
An example is C#'s String.Trim method. C# strings are immutable and if Trim doesn't have to do any work, a reference to the existing string is returned, otherwise a new string object with the trimmed content is returned.
How would I mimic this semantic in C++ given something close to the above method signature?
Your object must be a reference type for this to work. Let's give a toy example for strings:
class RefString {
public:
RefString() : ref(new std::string()) { }
RefString(const std::string& str) : ref(new std::string(str)) { }
RefString trim_trailing_newline() {
if (ref->back() == '\n') {
return RefString(ref->substr(0, ref->size()-1));
}
return *this;
}
size_t size() { return ref->size(); }
private:
std::shared_ptr<std::string> ref;
};
int main(int argc, char** argv) {
RefString s("test\n");
std::cout << s.size() << "\n";
std::cout << s.trim_trailing_newline().size() << "\n";
return 0;
}
You may always return const SomeImmutableObject&. Note though that assigning result to an object will invoke a copy.
SomeImmutableObject x = ManipulateIfNecessary(y); // will invoke a copy-ctor
The real trick would be the implementation. When the first "if" clause has an effect you will be presumably returning reference to temporary variable (bad thing to do). The newly created object would have to be dynamically allocated.
All, in all I do not think this is easily possible w/o some smart memory management.
A reasonable option is to implement SomeImmutableObject in a way that supports this - internally as a reference-counted smart-pointer to the logical state, while externally it may provide value semantics. (This can complicate usage from threaded code - you may want to read up on copy-on-write (COW) and why it became unpopular for implementing std::string.)
If you're stuck with an existing SomeImmutableObject implementation you can't change, and you can't wrap it with a reference-counted smart-pointer of sorts, then choices get limited.
It doesn't provide as clean caller usage, but you could make manipulationIsNeccessary a caller-accessible function, then have the caller call the "new object with new data" code - in a second function:
SomeImmutableObject obj;
const SomeImmutableObject& o =
manipulationIsNecessary(obj) ? newObjectWithNewData(obj) : obj;
...use o...
By having newObjectWithNewData be a separate function, you should get return value optimisation kicking in (though it's always best to check with your compiler/settings).
I have a thread-class Buffer (own made class), and many derived classes such as BufferTypeA, BufferTypeB...
Since I have to synchronize them in a certain order, I'm giving any of them an integer which represents the order to run certain task. I also have to know inside each thread Buffer which one is next to run the task, so I'm passing every BufferType a reference to an integer which all of them must share and I didn't want to make it Global.
I got lost at any point and I don't see where.
First I create all the BufferTypes from a class where I also define that shared integer as:
int currentThreadOrder;
And when creating the BufferTypes:
int position = 0;
if (NULL == bufferA) {
bufferA = new BufferTypeA(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferB) {
bufferB = new BufferPos(¤tThreadOrder, ++position,
waitCondition);
}
if (NULL == bufferC) {
bufferC = new BufferRtk(¤tThreadOrder, ++position,
waitCondition);
}
Then, in BufferTypeA header:
class BufferTypeA: public Buffer {
public:
BufferTypeA(int currentThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//..
}
And in cpp file:
BufferTypeA::BufferTypeA(int currentThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition):
Buffer(currentThreadOrder, threadConnectionOrder, waitCondition) { }
Now I'll show Buffer header:
class Buffer: public QThread {
public:
Buffer(int ¤tThreadOrder,
int threadConnectionOrder = 0,
QWaitCondition *waitCondition = NULL);
//...
protected:
QWaitCondition *waitCondition;
int threadConnectionOrder;
int ¤tThreadOrder; // Shared address
}
And finally the cpp:
Buffer::Buffer(int ¤tThreadOrder, int threadConnectionOrder, QWaitCondition *waitCondition) {
this->threadConnectionOrder = threadConnectionOrder;
this->waitCondition = waitCondition;
this->currentThreadOrder = currentThreadOrder;
}
And the error I'm getting is error: uninitialized reference member Buffer::currentThreadOrder.
I'm embarrased to ask, because it's going to be a simple problem with pointers and addresses, but I can't see where the problem is, so please help.
When you create a class with a data-member that is a reference, the reference needs to be assigned a value in the constructor initializer list.
References have to be given a value when they are created, they are not pointers. They have to start with a value and that value cannot be changed (while the contents that is pointed to by that value can be changed).
Essentially you can think of a reference as an alias for an existing variable. You can't give a friend a nickname if you don't have a friend :)
RESPONSE TO COMMENT:
You don't "share a reference" between objects. Each object will have its own reference to the same variable. When you "pass by reference" you are telling the compiler that you want the variable in your function to actually be the variable in your outer scope, rather than creating a new variable by value. This means that you only have one variable at one memory location. The reference is just memory in some other place that forwards you to that same memory location.
Think of this as call forwarding... I can have 15 phone numbers in 15 different countries. I can set them all up to forward calls to my cell in the US. So, people are calling me no matter which number they call.
Each of your classes just has another reference to forward the "phone calls" or variable reads/writes to that same memory location. So, you're not sharing a reference between classes, you're making sure that each class HAS a reference to the same underlying memory location.
Back to the metaphore, each class won't have the same phone, but each class' phone will forward to the same number (variable) none-the-less which lets them all set/get the same value in the end.
RESPONSE II:
Here's a simple example to get your head going, it's pretty easy to apply to your classes. I didn't compile it but it should work minus a typo or two possibly.
class A
{
public:
A(int& shared) : m_shared(shared)
{
//No actions needed, initializer list initializes
//reference above. We'll just increment the variable
//so you can see it's shared in main.
m_shared += 7;
}
void DoSomethingWithIt()
{
//Will always reflect value in main no matter which object
//we are talking about.
std::cout << m_shared << std::endl;
}
private:
//Reference variable, must be initialized in
//initializer list of constructor or you'll get the same
//compiler error again.
int& m_shared;
};
int main()
{
int my_shared_integer = 0;
//Create two A instances that share my_shared_integer.
//Both A's will initialize their internal reference to
//my_shared_integer as they will take it into their
//constructors "by reference" (see & in constructor
//signature) and save it in their initializer list.
A myFirstA(my_shared_integer);
A mySecondA(my_shared_integer);
//Prints 14 as both A's incremented it by 7 in constructors.
std::cout << my_shared_integer << std::endl;
}
you pass a pointer int* as 1st argument to BufferTypeA, which expects and int, while you said in your question you meant to use a int&. To do this, the ctor of BufferTypeA should take a int& and initialise it in an initialisation list (i.e. not within the { } part of the ctor) like
class BufferType {
int &Ref;
public:
BufferTypeA(int& ref) : Ref(ref) { /* ... */ }
};
and in your construction of BufferA you must not pass an address, but the reference, i.e.
int counter;
Buffer = new BufferType(counter);
You want code like this:
Buffer::Buffer(
int ¤tThreadOrder0,
const int threadConnectionOrder0,
QWaitCondition *const waitCondition0
) :
threadConnectionOrder(threadConnectionOrder0),
waitCondition(waitCondition0),
currentThreadOrder(currentThreadOrder0)
{}
The reason is related to the reason you cannot write
const double pi;
pi = 3.14;
but can write
const double pi = 3.14;
A reference is typically implemented as a constant pointer, to which one cannot assign an address after one has initialized the pointer. Your version of the code assigns, as in the first pi example. My version of the code initializes, as in the second pi example.
Is it possible to initialize a variable from a return parameter (by ref)? Say I have something like:
Car c; // <- don't want to create a new Car here!
if (findCar("beetle", c)) {
...
}
where if findCar succeeds, it returns true and fills c:
bool findCar(string name, Car& out) {
...
// return true if found
out = thecar;
return true;
}
Now, my class Car doesn't have a 0-argument constructor, so the above code fails to compile. Is there a way to keep c uninitialized until the call to findCar?
Solutions I thought of are:
adding a cheap 0-argument constructor to Car
switch to pointers (which I'd rather avoid)
Sort of. The problem is that a reference absolutely must refer to an actual object. So, if you return by reference then someone must create an object for that returned reference. Therefore if you can't find a matching object, it's not really meaningful to return a reference. If you pass a reference in, then you must create an object first, for the argument to refer to.
You could work around this for example as follows:
Car &findCar(const string &name) {
...
// return if found, else throw
if (found it) {
return thecar; // assuming `thecar` means some already-existing object,
// if it's a local variable then return by value!
} else {
throw std::runtime_error(name);
}
}
Caller does:
Car c = findCar("beetle");
or Car &c = findCar("beetle"); if they want to "see" the actual object found rather than a copy of it. If findCar wants callers to only ever see a copy, not some internal object, then of course you can return by value rather than by reference - the difference is one & in the function signature.
And someone somewhere has to handle the exception.
If you'd prefer to avoid exceptions then the right thing to return from a find function is a pointer (or other iterator). It's what the standard containers and algorithms do when searching, and there are special values (end iterators, or you could use null pointers) that mean "not found".
Whenever an object variable (which is not a pointer or reference) exists, it contains the whole data of the object, which means that it has to be always initialized, so yes, you will have to use one of your suggested solutions.
By the way, if you don't use a pointer or reference, you also can't store objects of derived classes in the variable, so i would suggest switching to pointers.
Object are initialized as soon as you declare them as variable.
If you want late initialization you have to use pointer and:
Car *c;
bool findCar(string name, Car * &out){
...
out = new Car();
}
don't forget to delete it
No, this isn't possible. If the parameter signature takes a car reference, it must point to a car object. You have two solutions for only having the object created at the right, as late as possible time, use pointers like this:
car* find_car(string name) {
...
return nullptr;
}
car* c = find_car(...);
if (c != nullptr) {
...
}
or to use exceptions, which probably isn't what you want
car find_car(string name) {
...
throw new runtime_error("car not found");
}
Basically declaring it as a reference means you're guaranteeing the object has been constructed, so that requirement needs to give. I'd use pointers personally.
You can return Car from your function:
struct Car
{
Car():_isValid(false){}
Car(const Car&);
bool isValid();
};
Car findCar (const string& name);
Car car = findCar("beetle");
if (car.isValid()){
...
}
other variant is to throw excpetion, if findCar cannot find any car:
struct Car
{
Car(const Car&);
};
Car findCar (const string& name) {
....
if (noCarFound) throw CarNotFoundException();
....
}
try{
Car car = findCar("beetle") {
}
catch (CarNotFoundException e) {
....
}
Or create Car constructor that accepts string
I am not very experienced at C++ but also I know this is not the cleanest solution.
However here is an approach:
bool findCar(string name, Car **out) {
// first make out to null
*out = NULL;
...
// if found
if(found){
*out = &thecar;
return true;
}
// otherwise return false. Notice that out remains pointing null
return false;
}
Now, anywhere in the code you should have:
Car *c; // <- You don't create a new Car here!
if (findCar("beetle", &c)) {
...
}
Hope you find it helpful