c++ create reference variable inside function - c++

Suppose I have the following function:
void myFunc(P& first, P& last) {
std::cout << first.child.grandchild[2] << endl;
// ...
}
Now, let's assume that first.child.grandchild[2] is too long for my purposes. For example, suppose it will appear frequently in equations inside myFunc(P&,P&). So, I'd like to create some sort of symbolic reference inside the function so that my equations would be less messy. How could I do this?
In particular, consider the code below. I need to know what statement I could insert so that not only would the output from line_1a always be the same as the output from line_1b, but also so that the output from line_2a would always be the same as the output from line_2b. In other words, I don't want a copy of the value of first.child.grandchild, but a reference or symbolic link to the object first.child.grandchild.
void myFunc(P& first, P& last) {
// INSERT STATEMENT HERE TO DEFINE "g"
std::cout << first.child.grandchild[2] << endl; // line_1a
std::cout << g[2] << endl; // line_1b
g[4] = X; // where X is an in-scope object of matching type
std::cout << first.child.grandchild[4] << endl; // line_2a
std::cout << g[4] << endl; // line_2b
//...
}

Say that the type of grandchild is T and size is N; then below is the way to create a reference for an array.
void myFunc(P& first, P& last) {
T (&g)[N] = first.child.grandchild;
...
}
I would not prefer pointer here, though it's also a possible way. Because, the static size of array is helpful to a static analyzer for range checking.
If you are using C++11 compiler then auto is the best way (mentioned by #SethCarnegie already):
auto &g = first.child.grandchild;

Use a pointer - then you can change it in the function.
WhateverGrandchildIs *ptr=&first.child.grandchild[2];
std::cout << *ptr << std::endl;
ptr=&first.child.grandchild[4];
std::cout << *ptr << std::endl;

Related

Add an element to a vector inside a struct, from within another struct

This is most probably trivial and I'm confusing struct allocation and pointers somehow, I apologize for this. I have read answers to similar questions but it didn't help. The code is, as always, way more complicted, this is a reduction from 3000+ lines of code to the gist.
The output I expected was
prep 1
main 1
Instead, I get
prep 1
main 0
This is the code:
#include <iostream>
#include <vector>
using namespace std;
struct Entry
{
vector<int> list;
};
struct Registry
{
vector<Entry> entries;
void prep()
{
Entry* entry = new Entry();
entries.push_back(*entry);
entry->list.push_back(0);
cout << "prep " << entry->list.size() << "\n";
}
};
int main()
{
Registry registry;
registry.prep();
cout << "main " << registry.entries[0].list.size() << "\n";
return 1;
}
You don't store pointers in your vector<Entry> so you should not use new. Instead add a default constructed Entry using emplace_back.
A C++17 approach:
void prep()
{
Entry& entry = entries.emplace_back(); // returns a ref the added element
entry.list.push_back(0);
cout << "prep " << entry.list.size() << "\n";
}
Prior to C++17:
void prep()
{
entries.emplace_back(); // does NOT return a ref the added element
Entry& entry = entries.back(); // obtain a ref to the added element
entry.list.push_back(0);
cout << "prep " << entry.list.size() << "\n";
}
If you do want to create and maniplate your Entry before adding it to entries, you can do that too and then std::move it into entries.
void prep()
{
Entry entry;
entry.list.push_back(0);
cout << "prep " << entry.list.size() << "\n";
entries.push_back(std::move(entry)); // moving is a lot cheaper than copying
}
The problem is the order of the prep() function. If you change to push an element into the Element object, and then push it tho the entries vector, the behavior will be the expected.
void prep()
{
Entry* entry = new Entry();
entry->list.push_back(0);
entries.push_back(*entry);
cout << "prep " << entry->list.size() << "\n";
}
This is happening, because you uses a copy in the entries list.
It is also possible to store the pointer of the object therefore you can edit the actual instance after you pushed to the entries vector.
Edit:
As Ted mentioned, there is a memory leak, because the entry created with the new operator never deleted. Another approach could be to use smart pointers (however, in this small example it seems overkill, just use reference)
void prep()
{
std::unique_ptr<Entry> entry = std::make_unique<Entry>();
entry->list.push_back(0);
entries.push_back(*entry.get()); // get the pointer behind unique_ptr, then dereference it
cout << "prep " << entry->list.size() << "\n";
} // unique_ptr freed when gets out of scope
You need to change the implementation of prep():
void prep()
{
Entry entry;
entry.list.push_back(0);
entries.emplace_back(entry);
cout << "prep " << entries.back().list.size() << "\n";
}
There is no need to allocate a Entry on the heap just to make a copy of it.

Changing the address of a pointer after construction

I've tried to create a minimal example of my problem. I'm trying to check if the address of an void pointer is NULL or not. The address should be overgiven by constructing the class, and should be const. I wrote the class below.
MyPointer.h:
public:
MyPointer(const void* activeApp) : m_activeApp(activeApp){
std::cout <<"adresse on construction: " << m_activeApp << std::endl;
};
MyPointer.cpp:
void printAdress();
private:
const void* m_activeApp;
};
The Methode "printAdress" should be able to print the correct address of the given pointer.
int main(void){
void* p_activeApp = nullptr;
std::cout << p_activeApp << std::endl;
MyPointer myPointer(p_activeApp);
std::cout << "Should be 0: " ;
myPointer.printAddress();
p_activeApp = new(bool);
std::cout << "Should be anything: ";
myPointer.printAddress();
}
void MyPointer::printAddress() {
std::cout << this->m_activeApp << std::endl;
};
Of course it doesn't work, because the m_activeApp still points to NULL, but how can I change this?
If you want to change what myPointer.m_activeApp points to, you have to set the pointer to a different value, simple as that. This pointer and p_activeApp are two distinct, independent pointers. Changing one does not change the other.
What you can do is to make one pointer a reference to the other pointer instead. Then, changing one would also change the other. This will work, though be warned, it won't be good programming style.
Pointers are integers (representing a memory location), so imagine void* to be a number. You set p_activeApp to 0, then you construct a MyPointer, and its internal pointer is set to 0.
Then you change the first number by using the new operator, p_activeApp now gets a value (to that new memory address), but there's no reason for m_activeApp to also change. It still points at 0, no matter what p_activeApp changes to.
I fixed it like this:
public:
MyPointer(void** activeApp) : m_pp_activeApp(activeApp) {
std::cout <<"address on construction: " << *m_pp_activeApp << std::endl;
};
void printAddress();
private:
void** m_pp_activeApp;
};
int main(void){
void* p_activeApp = nullptr;
void** pp_activeApp = &p_activeApp;
MyPointer myPointer(pp_activeApp);
std::cout << "Should be 0: " ;
myPointer.printAddress();
p_activeApp = new(bool);
std::cout << "Should be anything: ";
myPointer.printAddress();
}
void MyPointer::printAddress() {
std::cout << *m_pp_activeApp << std::endl;
};

calling function depending on index of array array of functions' names

making random actions in a game makes it really look like real...
so if a character has many capabilities like move, work, study... so in programming a function of those is called depending on some conditions. what we want is a more random and real-looking like action where no condition is there but depending on a random condition the character takes a random actions..
I thought to make actions (functions) in an array then declare a pointer to function and the program can randomly generate an index which on which the pointer to function will be assigned the corresponding function name from the array:
#include <iostream>
void Foo() { std::cout << "Foo" << std::endl; }
void Bar() { std::cout << "Bar" << std::endl; }
void FooBar(){ std::cout << "FooBar" << std::endl; }
void Baz() { std::cout << "Baz" << std::endl; }
void FooBaz(){ std::cout << "FooBaz" << std::endl; }
int main()
{
void (*pFunc)();
void* pvArray[5] = {(void*)Foo, (void*)Bar, (void*)FooBar, (void*)Baz, (void*)FooBaz};
int choice;
std::cout << "Which function: ";
std::cin >> choice;
std::cout << std::endl;
// or random index: choice = rand() % 5;
pFunc = (void(*)())pvArray[choice];
(*pFunc)();
// or iteratley call them all:
std::cout << "calling functions iteraely:" << std::endl;
for(int i(0); i < 5; i++)
{
pFunc = (void(*)())pvArray[i];
(*pFunc)();
}
std::cout << std::endl;
return 0;
}
the program works fine but I only is it good or there's an alternative. every comment is welcome
There is absolutely no point in converting function pointers to void* and back. Define an array of function pointers, and use it as a normal array. The syntax for the declaration is described in this Q&A (it is for C, but the syntax remains the same in C++). The syntax for the call is a straightforward () application after the indexer [].
void (*pFunc[])() = {Foo, Bar, FooBar, Baz, FooBaz};
...
pFunc[choice]();
Demo.
Note: Although function pointers work in C++, a more flexible approach is to use std::function objects instead.

Simulate std::vector with mixed const and non-const elements

I'd like to simulate a std::vector that has mixed const and non-const elements. More specifically, I want to have functions that operate on a vector and are allowed to see the entire vector but may only write to specific elements. The elements that can and cannot be written will be determined at runtime and may change during runtime.
One solution is to create a container that holds an array of elements and an equal sized array of booleans. All non-const access would be through a function that checks against the boolean array if the write is valid and throws an exception otherwise. This has the downside of adding a conditional to every write.
A second solution might be to have the same container but this time write access is done by passing an array editing function to a member function of the container. The container member function would let the array editing function go at the array and then check that it didn't write to the non-writable elements. This has the downside that the array editing function could be sneaky and pass around non-const pointers to the array elements, let the container function check that all is well, and then write to non-writable elements.
The last issue seems difficult to solve. It seems like offering direct writable access ever means we have to assume direct writable access always.
Are there better solutions?
EDIT: Ben's comment has a good point I should have addressed in the question: why not a vector of const and a vector of non-const?
The issue is that the scenario I have in mind is that we have elements that are conceptually part of one single array. Their placement in that array is meaningful. To use vectors of const and non-const requires mapping the single array that exist in concept to the two vectors that would implement it. Also, if the list of writable elements changes then the elements or pointers in the two vectors would need to be moved about.
I think you can accomplish what you wish with the following class, which is very simplified to illustrate the main concept.
template <typename T>
struct Container
{
void push_back(bool isconst, T const& item)
{
data.push_back(std::make_pair(isconst, item));
}
T& at(size_t index)
{
// Check whether the object at the index is const.
if ( data[index].first )
{
throw std::runtime_error("Trying to access a const-member");
}
return data[index].second;
}
T const& at(size_t index) const
{
return data[index].second;
}
T const& at(size_t index, int dummy) // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
T const& at(size_t index, int dummy) const // Without dummy, can't differentiate
// between the two functions.
{
return data[index].second;
}
std::vector<std::pair<bool, T> > data;
};
Here's a test program and its output.
#include <stdio.h>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <vector>
//--------------------------------
// Put the class definition here.
//--------------------------------
int main()
{
Container<int> c;
c.push_back(true, 10);
c.push_back(false, 20);
try
{
int value = c.at(0); // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
int value = c.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = c.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = c.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Accessing the data through a const object.
// All functions should work since they are returning
// const&.
Container<int> const& cref = c;
value = cref.at(0); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(0, 1); // Should work.
std::cout << "Got c[0]: " << value << "\n";
value = cref.at(1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
value = cref.at(1, 1); // Should work.
std::cout << "Got c[1]: " << value << "\n";
// Changing values ... should only work for '1'
try
{
c.at(0) = 100; // Show throw exception.
}
catch (...)
{
std::cout << "Expected to see this.\n";
}
c.at(1) = 200; // Should work.
std::cout << "Got c[1]: " << c.at(1) << "\n";
}
Output from running the program:
Expected to see this.
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Got c[0]: 10
Got c[0]: 10
Got c[1]: 20
Got c[1]: 20
Expected to see this.
Got c[1]: 200

Passing around an object in C++ by reference [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.
I have objects that I put into a std::vector. Later on I need to iterate through the vector and change some member variables in the objects in each position.
I think I want to pass the object once I have it by reference to a function to operate on it, but I seem to be getting an error:
Non-const lvalue reference to type 'Object' cannot bind to a value of unrelated type 'Object *'
Here is the general gist with code between omitted:
Object* o1 = Object::createWithLocation(p.x, p.y);
v.push_back(o1);
// later on
for (int f=0; f < v.size(); f++)
{
Object* obj1 = v.at(f);
addChild(h->createLayer(obj1), 3); // add the HUD
}
createLayer is defined at:
static PlantingHUD* createLayer(Object &o);
Can anyone explain my confusion between pointers and passing by reference? Do I have to do a cast of some sort?
static PlantingHUD* createLayer(Object &o);
this method need a reference to Object as the parameter,
but your input is a pointer.
Object* obj1 = v.at(f);
addChild(h->createLayer(obj1), 3); // add the HUD
That's the problem.
void foo(Object o)
Declares a function, foo, which will begin execution with a fresh, new, instance of class 'Object' called 'o'.
This is called "passing by value", but it's more accurately 'copying' because what foo receives is it's own, personal copy of the Object instances we call foo with. When "foo" ends, the "Object o" it knew, fed and put through school, will cease to be.
void foo(Object& o)
Declares a function, foo, which will begin executing with a reference to an existing instance of an 'Object', this reference will be called 'o'. If you poke or prod it, you will be changing the original.
This is called "pass by reference".
void foo(Object* o)
Declares a function, foo, which will begin executing with a variable, called "o", containing the address of what is supposed to be an instance of "Object". If you change this variable, by doing something like "o = nullptr", it will only affect the way things look inside foo. But if you send Samuel L Jackson to the address, he can deliver furious vengance that lasts beyond the lifetime of foo.
void foo(Object*& o)
Declares a function, foo, which will begin executing with a variable called "o", which is a reference to a pointer to an instance of object o - it's like an alias, except that without compiler optimization, it's actually implemented by the compiler using a sort of pointer.
Lets try these separately.
#include <iostream>
#include <cstdint>
struct Object
{
int m_i;
void event(const char* what, const char* where)
{
std::cout <<
what<< " " << (void*)this <<
" value " << m_i <<
" via " << where <<
std::endl;
}
// Construct an object with a specific value.
Object(int i) : m_i(i)
{
event("Constructed", "Operator(int i)");
}
// This is called the copy constructor, create one object from another.
Object(const Object& rhs) : m_i(rhs.m_i)
{
event("Constructed", "Operator(const Object&)");
}
// This is how to handle Object o1, o2; o1 = o2;
Object& operator=(const Object& rhs)
{
m_i = rhs.m_i;
event("Assigned", "operator=");
return *this;
}
// Handle destruction of an instance.
~Object() { event("Destructed", "~Object"); }
};
void foo1(Object o)
{
std::cout << "Entered foo1, my o has value " << o.m_i << std::endl;
// poke our local o
o.m_i += 42;
std::cout << "I changed o.m_i, it is " << o.m_i << std::endl;
}
void foo2(Object* o)
{
std::cout << "Foo2 starts with a pointer, it's value is " << (uintptr_t)o << std::endl;
std::cout << "That's an address: " << (void*)o << std::endl;
std::cout << "m_i of o has the value " << o->m_i << std::endl;
o->m_i += 42;
std::cout << "I've changed it tho, now it's " << o->m_i << std::endl;
}
void foo3(Object& o)
{
std::cout << "foo3 begins with a reference called o, " << std::endl <<
"which is sort of like a pointer but the compiler does some magic " << std::endl <<
"and we can use it like a local concrete object. " <<
std::endl <<
"Right now o.m_i is " << o.m_i <<
std::endl;
o.m_i += 42;
std::cout << "Only now, it is " << o.m_i << std::endl;
}
void foo4(Object*& o)
{
std::cout << "foo4 begins with a reference to a pointer, " << std::endl <<
"the pointer has the value " << (uintptr_t)o << " which is " <<
(void*)o <<
std::endl <<
"But the pointer points to an Object with m_i of " << o->m_i << std::endl <<
"which we accessed with '->' because the reference is to a pointer, " <<
"not to an Object." <<
std::endl;
o->m_i += 42;
std::cout << "I poked o's m_i and now it is " << o->m_i << std::endl;
// Now for something really dastardly.
o = new Object(999);
std::cout << "I just changed the local o to point to a new object, " <<
(uintptr_t)o << " or " << (void*)o << " with m_i " << o->m_i <<
std::endl;
}
int main()
{
std::cout << "Creating our first objects." << std::endl;
Object o1(100), o2(200);
std::cout << "Calling foo1 with o1" << std::endl;
foo1(o1);
std::cout << "back in main, o1.m_i is " << o1.m_i << std::endl;
std::cout << "Calling foo2 with &o1" << std::endl;
foo2(&o1);
std::cout << "back in main, o1.m_i is " << o1.m_i << std::endl;
std::cout << "Calling foo3(o2), which looks like the way we called foo1." << std::endl;
foo3(o2);
std::cout << "back in main, o2.m_i is " << o2.m_i << std::endl;
std::cout << "Creating our pointer." << std::endl;
Object* optr;
std::cout << "Setting it to point to 'o2'" << std::endl;
optr = &o2;
std::cout << "optr now has the value " << (uintptr_t)optr <<
" which is the address " << (void*)optr <<
" which points to an Object with m_i = " << optr->m_i <<
std::endl;
foo4(optr);
std::cout << "back in main, o2 has the value " << o2.m_i << std::endl <<
"and now optr has the value " << (uintptr_t)optr << std::endl <<
"and optr->m_i is now " << optr->m_i <<
std::endl;
if (optr != &o2)
delete optr; // otherwise we'd technically be leaking memory.
return 0;
}
Live demo on ideone.com.
Passing by Value
This term confuses people early in their C++ development because, in lay terms, it sounds like this is what "Object& foo" would do.
The term "pass by value" actually arises from what the language has to do to call such a function, to value-wise copy the whole of the original object/struct onto the stack or, in the case where a copy ctor is available, forward them to a value-wise constructor and recreate a copy of the original, value-by-value.
Pass-by-value should be used for most simple cases where you do not want side-effects on the values in your current scope from the function you are calling.
bool checkWidthdrawl(Dollars balance, Dollars amountToWithdraw)
{
// it's safe for me to change "balance" here because balance is mine
}
vs
bool checkWidthdrawl(Dollars& balance, Dollars amountToWithdraw)
{
balance -= amountToWithdraw;
if (balance < 0)
std::complaint << "My account seems to be missing $" << amountToWithdraw;
}
However, passing by reference can become expensive.
struct FourK { char a[1024], b[1024], c[1024], d[1024]; }
If you pass this around by value all day, you risk blowing up your stack at some point, as well as spending daft amounts of time copying all those bytes.
void foo(int i); // Unless you need to see the changes to i, this is perfectly fine.
void foo(FourK f); // Someone should hunt you down and yell "PEANUT" in your ear.
Passing by reference
References are really a contract over the pointer system that allow the language to ensure you're really talking about a concrete instance of an object, and thus allow you to refer to a pre-existing instance of a value outside of a function.
Of course, there are ways to break this, but the language tries very, very hard to make them difficult to do. For example, try adding this to the above code:
Object& makeObjectNotWar(int i)
{
Object thisObjectGoesAway(i);
return thisObjectGoesAway /*right about now*/;
}
You can also provide callers with an assurance that the function won't have any side effects on a variable with the "const" modifier.
void fooc(const Object& o)
{
o.m_i += 42; // Error
}
You can even use that within a function as a hint to yourself (and the compiler) that you don't want to accidentally change a value, here's a case where it can provide an optimization hint to the compiler:
std::vector<int> foo;
add1000valuesTo(foo);
const size_t fooSize = foo.size();
for (size_t i = 0; i < fooSize; ++i) {
// ... stuff you're sure won't decrease foo.size()
}
Without the const fooSize
for (size_t i = 0; i < foo.size(); ++i) {
The compiler has to start by assuming that "foo.size()" could be changed at any given iteration of the loop. It can probably figure out that it doesn't, but by giving it the hint, you've saved a little compile time, possibly improved your performance, and made it easier for a human to tell exactly what behavior you expected. Downside: If your loop does actually change the size of foo, you'll find out by bug reports :(
One last thing to know about pass-by-reference is that C++ references aren't protected or "ref counted". The language only promises that a reference will be valid for the duration of its scope, so long as you don't do anything stupid like, say, call something that deletes the object.
// Author intended this function to be called
// by the owner of a Dog.
void doneWithFoo(Dog& dog)
{
Dog* deadDog = &dog;
delete deadDog;
}
Rover& Babysitter::babysitDog(Dog& rover, int hours)
{
rover.feed(FeedType::Donut);
if (rover.pooped())
doneWithDog(rover);
// ...
return rover; // I have a bad feeling about this.
}
Obviously, you're not expecting "babysitDog" to result in the dog being disposed of. But bear in mind that because we passed in a reference, it to "babysitDog" that it's also gone from the caller too, and if that was using a reference... rover's dead, Dave, dead.
As with pointers, if you're going to store references beyond the scope in which you have access to them, then you become responsible for making sure the objects being referenced stick around or that the references are removed from the container before the objects do go away.