For example:
#include <iostream>
#include <deque>
int func(int a){
std::deque<int> obj;
obj.push_back(a);
for(std::deque<int>::iterator it = obj.begin(); it!=obj.end();++it)
std::cout << *it << '\n';
return 0;
}
int main()
{
int x=2;
func(x);
func(x);
}
output is :
2
2
so its mean that deque object destroy after reach end scope of func. And i cant do nothing with this, except return value or add to global scope? No way to change behavior of this object with adding static to him or static pointer or something else? I mean that with pure C++ its look like :
int func(int a){
static int *p = new int;
}
and value will be store between function calls but how to do same with stl containers i don't know.
If you really want it to be static, make it so:
static std::deque<int> obj;
although this is probably a bad idea: conceptually, you have hidden state in the program, and practically, there's a possibility of accessing the object after it's been destroyed. (You can fudge around the lifetime issues by using dynamic allocation and leaking the object, as demonstrated in Drax's answer, if you really want to go down this particular road of pain).
Better would be to encapsulate the state in a class. Then you can control exactly when it's created and destroyed, and have more than one instance if you like.
class thing {
public:
int func(int a) {
obj.push_back(a);
// and print it
}
private:
std::deque<int> obj;
};
int main() {
thing t;
t.func(2); // 2
t.func(3); // 2 3
}
If you want to remember data between function calls, store it elsewhere, or as a last resort make it static.
So, either go with Mike Seymour's answer to make it a member of a class, or hold onto it in main, and pass it to the function, making sure you pass by reference if you wish to change it:
int func(int a, std::deque<int> & obj){
//.. as you were
}
From main, make the data and pass it in:
int main()
{
int x=2;
std::deque<int> obj;
func(x, obj);
func(x, obj);
}
Simply :
int func(int a){
static std::deque<int>* obj = new std::deque<int>;
obj->push_back(a);
for(std::deque<int>::iterator it = obj->begin(); it!=obj->end();++it)
std::cout << *it << '\n';
}
But i'm not sure that's a good idea :)
Related
I have a Storage class that keeps a list of Things:
#include <iostream>
#include <list>
#include <functional>
class Thing {
private:
int id;
int value = 0;
static int nextId;
public:
Thing() { this->id = Thing::nextId++; };
int getId() const { return this->id; };
int getValue() const { return this->value; };
void add(int n) { this->value += n; };
};
int Thing::nextId = 1;
class Storage {
private:
std::list<std::reference_wrapper<Thing>> list;
public:
void add(Thing& thing) {
this->list.push_back(thing);
}
Thing& findById(int id) const {
for (std::list<std::reference_wrapper<Thing>>::const_iterator it = this->list.begin(); it != this->list.end(); ++it) {
if (it->get().getId() == id) return *it;
}
std::cout << "Not found!!\n";
exit(1);
}
};
I started with a simple std::list<Thing>, but then everything is copied around on insertion and retrieval, and I didn't want this because if I get a copy, altering it does not reflect on the original objects anymore. When looking for a solution to that, I found about std::reference_wrapper on this SO question, but now I have another problem.
Now to the code that uses them:
void temp(Storage& storage) {
storage.findById(2).add(1);
Thing t4; t4.add(50);
storage.add(t4);
std::cout << storage.findById(4).getValue() << "\n";
}
void run() {
Thing t1; t1.add(10);
Thing t2; t2.add(100);
Thing t3; t3.add(1000);
Storage storage;
storage.add(t3);
storage.add(t1);
storage.add(t2);
temp(storage);
t2.add(10000);
std::cout << storage.findById(2).getValue() << "\n";
std::cout << storage.findById(4).getValue() << "\n";
}
My main() simply calls run(). The output I get is:
50
10101
Not found!!
Although I was looking for:
50
10101
50
Question
Looks like the locally declared object t4 ceases to exist when the function returns, which makes sense. I could prevent this by dynamically allocating it, using new, but then I didn't want to manage memory manually...
How can I fix the code without removing the temp() function and without having to manage memory manually?
If I just use a std::list<Thing> as some suggested, surely the problem with t4 and temp will cease to exist, but another problem will arise: the code won't print 10101 anymore, for example. If I keep copying stuff around, I won't be able to alter the state of a stored object.
Who is the owner of the Thing in the Storage?
Your actual problem is ownership. Currently, your Storage does not really contain the Things but instead it is left to the user of the Storage to manage the lifetime of the objects you put inside it. This is very much against the philosophy of std containers. All standard C++ containers own the objects you put in them and the container manages their lifetime (eg you simply call v.resize(v.size()-2) on a vector and the last two elements get destroyed).
Why references?
You already found a way to make the container not own the actual objects (by using a reference_wrapper), but there is no reason to do so. Of a class called Storage I would expect it to hold objects not just references. Moreover, this opens the door to lots of nasty problems, including undefined behaviour. For example here:
void temp(Storage& storage) {
storage.findById(2).add(1);
Thing t4; t4.add(50);
storage.add(t4);
std::cout << storage.findById(4).getValue() << "\n";
}
you store a reference to t4 in the storage. The thing is: t4s lifetime is only till the end of that function and you end up with a dangling reference. You can store such a reference, but it isnt that usefull because you are basically not allowed to do anything with it.
Aren't references a cool thing?
Currently you can push t1, modify it, and then observe that changes on the thingy in Storage, this might be fine if you want to mimic Java, but in c++ we are used to containers making a copy when you push something (there are also methods to create the elements in place, in case you worry about some useless temporaries). And yes, of course, if you really want you can make a standard container also hold references, but lets make a small detour...
Who collects all that garbage?
Maybe it helps to consider that Java is garbage-collected while C++ has destructors. In Java you are used to references floating around till the garbage collector kicks in. In C++ you have to be super aware of the lifetime of your objects. This may sound bad, but acutally it turns out to be extremely usefull to have full control over the lifetime of objects.
Garbage? What garbage?
In modern C++ you shouldnt worry to forget a delete, but rather appreciate the advantages of having RAII. Acquiring resources on initialzation and knowing when a destructor gets called allows to get automatic resource management for basically any kind of resource, something a garbage collector can only dream of (think of files, database connections, etc.).
"How can I fix the code without removing the temp() function and without having to manage memory manually?"
A trick that helped me a lot is this: Whenever I find myself thinking I need to manage a resource manually I stop and ask "Can't someone else do the dirty stuff?". It is really extremely rare that I cannot find a standard container that does exactly what I need out of the box. In your case, just let the std::list do the "dirty" work.
Can't be C++ if there is no template, right?
I would actually suggest you to make Storage a template, along the line of:
template <typename T>
class Storage {
private:
std::list<T> list;
//....
Then
Storage<Thing> thing_storage;
Storage<int> int_storage;
are Storages containing Things and ints, respectively. In that way, if you ever feel like exprimenting with references or pointers you could still instantiate a Storage<reference_wrapper<int>>.
Did I miss something?...maybe references?
I won't be able to alter the state of a stored object
Given that the container owns the object you would rather let the user take a reference to the object in the container. For example with a vector that would be
auto t = std::vector<int>(10,0); // 10 element initialized to 0
auto& first_element = t[0]; // reference to first element
first_element = 5; // first_element is an alias for t[0]
std::cout << t[0]; // i dont want to spoil the fun part
To make this work with your Storage you just have to make findById return a reference. As a demo:
struct foo {
private:
int data;
public:
int& get_ref() { return data;}
const int& get_ref() const { return data;}
};
auto x = foo();
x.get_ref = 12;
TL;DR
How to avoid manual resource managment? Let someone else do it for you and call it automatic resource management :P
t4 is a temporary object that is destroyed at exit from temp() and what you store in storage becomes a dangling reference, causing UB.
It is not quite clear what you're trying to achieve, but if you want to keep the Storage class the same as it is, you should make sure that all the references stored into it are at least as long-lived as the storage itself. This you have discovered is one of the reasons STL containers keep their private copies of elements (others, probably less important, being—elimination of an extra indirection and a much better locality in some cases).
P.S. And please, can you stop writing those this-> and learn about initialization lists in constructors? >_<
In terms of what your code actually appears to be doing, you've definitely overcomplicated your code, by my estimation. Consider this code, which does all the same things your code does, but with far less boilerplate code and in a way that's far more safe for your uses:
#include<map>
#include<iostream>
int main() {
std::map<int, int> things;
int & t1 = things[1];
int & t2 = things[2];
int & t3 = things[3];
t1 = 10;
t2 = 100;
t3 = 1000;
t2++;
things[4] = 50;
std::cout << things.at(4) << std::endl;
t2 += 10000;
std::cout << things.at(2) << std::endl;
std::cout << things.at(4) << std::endl;
things.at(2) -= 75;
std::cout << things.at(2) << std::endl;
std::cout << t2 << std::endl;
}
//Output:
50
10101
50
10026
10026
Note that a few interesting things are happening here:
Because t2 is a reference, and insertion into the map doesn't invalidate references, t2 can be modified, and those modifications will be reflected in the map itself, and vise-versa.
things owns all the values that were inserted into it, and it will be cleaned up due to RAII, and the built-in behavior of std::map, and the broader C++ design principles it is obeying. There's no worry about objects not being cleaned up.
If you need to preserve the behavior where the id incrementing is handled automatically, independently from the end-programmer, we could consider this code instead:
#include<map>
#include<iostream>
int & insert(std::map<int, int> & things, int value) {
static int id = 1;
int & ret = things[id++] = value;
return ret;
}
int main() {
std::map<int, int> things;
int & t1 = insert(things, 10);
int & t2 = insert(things, 100);
int & t3 = insert(things, 1000);
t2++;
insert(things, 50);
std::cout << things.at(4) << std::endl;
t2 += 10000;
std::cout << things.at(2) << std::endl;
std::cout << things.at(4) << std::endl;
things.at(2) -= 75;
std::cout << things.at(2) << std::endl;
std::cout << t2 << std::endl;
}
//Output:
50
10101
50
10026
10026
These code snippets should give you a decent sense of how the language works, and what principles, possibly unfamiliar in the code I've written, that you need to learn about. My general recommendation is to find a good C++ resource for learning the basics of the language, and learn from that. Some good resources can be found here.
One last thing: if the use of Thing is critical to your code, because you need more data saved in the map, consider this instead:
#include<map>
#include<iostream>
#include<string>
//Only difference between struct and class is struct sets everything public by default
struct Thing {
int value;
double rate;
std::string name;
Thing() : Thing(0,0,"") {}
Thing(int value, double rate, std::string name) : value(value), rate(rate), name(std::move(name)) {}
};
int main() {
std::map<int, Thing> things;
Thing & t1 = things[1];
t1.value = 10;
t1.rate = 5.7;
t1.name = "First Object";
Thing & t2 = things[2];
t2.value = 15;
t2.rate = 17.99999;
t2.name = "Second Object";
t2.value++;
std::cout << things.at(2).value << std::endl;
t1.rate *= things.at(2).rate;
std::cout << things.at(1).rate << std::endl;
std::cout << t1.name << "," << things.at(2).name << std::endl;
things.at(1).rate -= 17;
std::cout << t1.rate << std::endl;
}
Based on what François Andrieux and Eljay have said (and what I would have said, had I got there first), here is the way I would do it, if you want to mutate objects you have already added to a list. All that reference_wrapper stuff is just a fancy way of passing pointers around. It will end in tears.
OK. here's the code (now edited as per OP's request):
#include <iostream>
#include <list>
#include <memory>
class Thing {
private:
int id;
int value = 0;
static int nextId;
public:
Thing() { this->id = Thing::nextId++; };
int getId() const { return this->id; };
int getValue() const { return this->value; };
void add(int n) { this->value += n; };
};
int Thing::nextId = 1;
class Storage {
private:
std::list<std::shared_ptr<Thing>> list;
public:
void add(const std::shared_ptr<Thing>& thing) {
this->list.push_back(thing);
}
std::shared_ptr<Thing> findById(int id) const {
for (std::list<std::shared_ptr<Thing>>::const_iterator it = this->list.begin(); it != this->list.end(); ++it) {
if (it->get()->getId() == id) return *it;
}
std::cout << "Not found!!\n";
exit(1);
}
};
void add_another(Storage& storage) {
storage.findById(2)->add(1);
std::shared_ptr<Thing> t4 = std::make_shared<Thing> (); t4->add(50);
storage.add(t4);
std::cout << storage.findById(4)->getValue() << "\n";
}
int main() {
std::shared_ptr<Thing> t1 = std::make_shared<Thing> (); t1->add(10);
std::shared_ptr<Thing> t2 = std::make_shared<Thing> (); t2->add(100);
std::shared_ptr<Thing> t3 = std::make_shared<Thing> (); t3->add(1000);
Storage storage;
storage.add(t3);
storage.add(t1);
storage.add(t2);
add_another(storage);
t2->add(10000);
std::cout << storage.findById(2)->getValue() << "\n";
std::cout << storage.findById(4)->getValue() << "\n";
return 0;
}
Output is now:
50
10101
50
as desired. Run it on Wandbox.
Note that what you are doing here, in effect, is reference counting your Things. The Things themselves are never copied and will go away when the last shared_ptr goes out of scope. Only the shared_ptrs are copied, and they are designed to be copied because that's their job. Doing things this way is almost as efficient as passing references (or wrapped references) around and far safer. When starting out, it's easy to forget that a reference is just a pointer in disguise.
Given that your Storage class does not own the Thing objects, and every Thing object is uniquely counted, why not just store Thing* in the list?
class Storage {
private:
std::list<Thing*> list;
public:
void add(Thing& thing) {
this->list.push_back(&thing);
}
Thing* findById(int id) const {
for (auto thing : this->list) {
if (thing->getId() == id) return thing;
}
std::cout << "Not found!!\n";
return nullptr;
}
};
EDIT: Note that Storage::findById now returns Thing* which allows it to fail gracefully by returning nullptr (rather than exit(1)).
I have following code
#include <iostream>
#include <vector>
using namespace std;
struct foo {
struct bar {
int foobar;
};
vector<bar*> barp;
bar & insert(int v){
bar * b = new bar();
(*b).foobar = v;
barp.push_back(b);
return *b;
}
void edit(bar & b, int v){
b.foobar = v;
}
};
int main() {
foo f;
foo::bar b = f.insert(5);
f.edit(b, 10);
std::cout << (b.foobar == 10?"true":"false") << std::endl;//now ok
std::cout << (b.foobar == 5?"true":"false") << std::endl;//now ok
std::cout << ((*f.barp[0]).foobar == 10?"true":"false") << std::endl;//after edit, still returns false
std::cout << ((*f.barp[0]).foobar == 5?"true":"false") << std::endl;//after edit, returns true
return 0;
}
Could someone explain me, why doesnt the "b.foobar" change to 10? Doesnt the b have the same address as the one saved in f.barp[0]?
EDIT:Thanks for answers, adding reference to void edit(bar & b, int v) does, of course, make sense. However adding reference to "bar & insert" doesnt seem to change anything, as the (*f.barp[0]).foobar stays unchanged after edit, even though insert should return reference now.
Doesn't the b have the same address as the one saved in f.barp[0]?
No, it does not. You return the object by value from the insert, i.e.
bar insert(int v)
^^^
Returning by value implies a copy: a new bar is constructed using a copy constructor, and the original one is discarded*.
To get the results that you expect, return bar& from insert:
bar& insert(int v) {
// ^
}
Similarly, edit should take its parameter by reference if you would like all functions to work on the same object.
* If it were not for you storing the pointer in a collection, this would also create a memory leak. Your program does have memory leak, too, but you can fix it by deleting objects in the barp vector.
Because you're passing the parameter to edit() by value, instead of by reference.
edit() ends up modifying a copy of the original object, which then immediately gets thrown away.
Also, you are returning a copy of the record from insert(), as well.
Your insert() must return a pointer, instead of a copy of the new record. You must also pass a pointer to edit(), too.
Doesnt the b have the same address as the one saved in f.barp[0]?
No, it does not. Every time you use bar with no further qualifications as an argument or return type, you are asking for a copy to be made. In this case, that means both the variable b in main and the variable b in edit are copies.
For this toy example, you can make the program do what you expected with these changes:
- bar insert(int v){
+ bar &insert(int v){
- void edit(bar b, int v){
+ void edit(bar &b, int v){
- foo::bar b = f.insert(5);
+ foo::bar &b = f.insert(5);
If you do not understand what that does or why, please consult a C++ textbook for an explanation of "references".
(If you've never seen the above -/+ notation before, it means "replace each line marked with a minus sign with the corresponding line marked with a plus sign.")
foo::bar b = f.insert(5);
This b object is different from *f.barp[0] since it is created from returned reference.
To make this work, change this line to
foo::bar& b = f.insert(5);
That way you are creating a reference to the object which you just inserted in the vector.
I was about to ask a rather simple beginner question the other day about a c++ function I was working on when I realized I hadn't released the memory for my function. That never seems to end well around here.
It seems like this would be a common question but I wasn't able to find anything at my level of understanding in c++
How would I properly free memory in this code
#include <iostream>
class thing{
public:
int a;
};
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
int main(){
thing thing1 = makeThing();
std::cout << "a: " << thing1.a << std::endl;
return 0;
}
As far as I know I'm not able to free it after the function terminates.
I tried this:
delete &thing1;
but based on the core dump, I assume that’s not the way to do it.
Since you return by value, that means you return a copy of the object. The original object, created by new things, can't be reached after the function returns (not reliably anyway).
You can return a pointer:
thing* makeThing(){
thing *t = new thing;
t -> a = 5;
return t;
}
And delete that.
But you should really just return an object, and not even allocate anything with new in this case.
Sometimes the simplest way to free memory is to not have allocated it to begin with:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
The reason what you're trying to do doesn't work is that when you have:
delete &thing1;
that's the address of your local object... that's not the address of what you actually allocated. That one got copied into yours, and now you have no way to access it.
If you wanted to allocate your thing, you would need to return the pointer directly. Preferably, wrapped somehow:
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return t;
}
thing makeThing(){
thing *t = new thing;
t -> a = 5;
return *t;
}
Leads to an immediate memory leak. The t variable will go out of scope after makeThing() returns, and the allocated memory will never be released or accessible for release with an appropriate delete statement.
There's a copy of the newly created t returned.
To fix it just create a local variable and retun a copy:
thing makeThing(){
thing t;
t.a = 5;
return t;
}
If you really want to use new this is the right way to do it. This code is C++11, so you may need to turn on some option if that is not already the default in the compiler you are using. I habitually use C++11, since the improvements in that version of the language are really worthwhile.
#include <iostream>
#include <memory>
#include <ostream>
class thing {
public:
int a;
};
std::ostream& operator<<(std::ostream& os, const thing& t) {
os << t.a;
return os;
}
std::unique_ptr<thing> makeThing() {
std::unique_ptr<thing> t(new thing);
t->a = 5;
return std::move(t);
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << *thing1 << std::endl;
return 0;
}
But really if all you want to do is create an object there is no need to allocate it on the heap. You can just do it like the code below. Notice that the object is created without the use of new. The object is copied when it is returned from makeThing(), and the compiler uses the default copy constructor for class thing (which I did not replace) when doing that.
#include <iostream>
#include <ostream>
thing makeThing() {
thing t;
t.a = 5;
return t;
}
int main() {
auto thing1 = makeThing();
std::cout << "a: " << thing1 << std::endl;
return 0;
}
The ostream inserter does not need to change, so I omitted it. Same for the class definition.
I have a simple test where I am trying to bind a weak_ptr argument to a global function that takes a weak_ptr, and invokes a method if the backing pointer is still valid.
This seems to work when I create a lambda with the weak pointer. It also works if I call the global method directly, with the weak_ptr. However if I bind the global function to the weak_ptr in advance, it does not seem to work. Following watered down code illustrates the question.
I must be missing something simple. Any clues?
#include <iostream>
#include <functional>
#include <algorithm>
#include <memory>
using namespace std;
class MyValue : public enable_shared_from_this<MyValue>
{
public:
MyValue (int i)
{
value = i;
}
~MyValue()
{
}
int getValue() { return value; }
void printValue() { cout << value << endl; }
private:
int value;
};
void callWeakFunction (weak_ptr<MyValue> weakValue)
{
shared_ptr<MyValue> strongPtr = weakValue.lock();
if (strongPtr)
{
strongPtr->printValue();
}
else
{
cout << "Sorry, your backing pointer is gone" << endl;
}
}
int main()
{
weak_ptr<MyValue> weakValue;
// Try binding a global function to the weak pointer, doesn't seem to work
function<void()> weakPrintValue = bind(callWeakFunction, weakValue);
#if 0
// Create a lambda - this works fine
function<void()> weakPrintValue ([&weakValue]()
{
shared_ptr<MyValue> ptr = weakValue.lock();
if(ptr)
{
ptr->printValue();
}
else
{
cout << "Sorry, backing pointer is gone" << endl;
}
});
#endif
{
shared_ptr<MyValue> value = make_shared<MyValue>(7);
weakValue = value;
// Backing pointer is present
weakPrintValue(); // This does not work, but callWeakFunction (weakValue) works fine
}
// No backing pointer
weakPrintValue();
}
Resulting output:
Sorry, your backing pointer is gone
Sorry, your backing pointer is gone
Expecting the first weakPrintValue to print the value (7)
I think you want to wrap the weak_ptr in ref() to evaluate it lazily:
function<void()> weakPrintValue = bind(callWeakFunction, ref(weakValue));
I wouldn't expect either to work. In both cases you're capturing the initial value of weak_value when it is empty. To be affected by the subsequent assignment to it you need to capture by reference instead. So in the lambda you need [&weak_value], and for the bind you need
bind(callWeakFunction, cref(weakValue));
I believe bind() captures weakValue by value. It returns resulting object that has it's own copy of weakValue. When you change local weakValue it does not affect the copy inside of the object returned by bind().
I'm trying make number guessing game with qt creator. I need to access a variable from another function. I was able to do that on python by adding "self." to beggining of variable but I can't do it on C++. Here's a sample what I am trying to do:
void function1()
{
int i;
}
void function2()
{
I need to access i here.
}
Thanks for help.
You could use pointers, classes or global variable ( I'd recommend pointers or a class tho)
void f1(int *iPtr)
{
cout << "value= " <<*iPtr << endl;
}
void f2(int *iPtr)
{
*iPtr = *iPtr + 5; // access ( modify ) variable here
cout << "after addition = " << *iPtr << endl;
}
int main()
{
int i = 5;
int *iPtr;
iPtr = &i; // point pointer to location of i
f1(iPtr);
f2(iPtr);
// after f1() value of i == 5, after f2() value of i == 10
}
I believe the equivalent behavior in C++ would be a member variable.
If you're not already, I'd suggest using a class. So, in your header file define it something like this:
class MyClass {
public:
void function1();
void function2();
private:
int i;
};
If you're not using C++ classes, then you can define "i" in the header file but that will make it global - in essense. And, probably not the best practice.
It is not possible to access a variable from another function since they exist only on the stack and they are destroyed when the function exits. Use a global variable.
You could declare i as a global variable and just assign it the random number once you have chosen it. That way you could still generate a random number and use it in another function.
int i;
void function1()
{
int randNum;
// get random number here
i = randNum;
}
void function2()
{
// do stuff with i here
}