People, I am new to all this programming talk. Up until now it was quite easy to find answers by googling them but right here I have big trouble expressing what I want to ask, let me try: Erasing a vector calls the destructor before freeing the memory, right? Now how does a struct-vector react, if it is destructed? One does not define a destructor for these things, but is it correct to assume that if a struct is "destructed" each of its members' destructors will be called as well?
Let me give you an example:
#include <string>
#include <vector>
struct ding_t {
std::string dang;
} foo;
strung boom_t {
vector <ding_t> chuck;
} bar;
int main () {
vector <boom_t> tom;
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
tom.erase();
return 0;
}
in this case, will the memory allocated by
tom[4].chuck.resize(5);
be freed as well? Sorry for my vocabulary, but at this moment I am trying to move from pointers to the more sophisticated cpp language equivalent of vectors. I hope I got my point across. Thanks in advance guys and please just redirect me if this has already been asked, as I've said, I don't know how to circumscribe this question.
Yes, the memory will be freed automatically.
When a vector is destructed it will call the destructor of all the elements it contains. You didn't define a destructor for your struct so the compiler will provide a default one for you (that does nothing).
However if your vector contains pointers to objects it will be your responsibility to call the destructor on the objects before destructing the vector (because the vector will call the destructor of the pointers, not the pointed objects), if you have no other way to access them later.
See http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.11 for the answer to your question and the entire article for a very good treatment of destructors in C++.
As to your second question: yes, the memory allocated by tom[4].chuck.resize(5); will get freed as well, since it is the vector's responsibility to manage its own memory allocations (which is the case for the "resize()" call.)
Answer: Since you are not allocating the Object dynamically with the new operator, you dont have to deallocate them manually.
It's done automatically for you.
Ok. Back to your code :)
If you want to erase the 6th element then use tom.erase (tom.begin()+5) .
And if you want to erase all elements then use tom.erase (tom.begin(),tom.end() ) .
To erase the first 3 elements use tom.erase (tom.begin(),tom.begin()+3).
#include <string>
#include <vector>
using namespace std;
struct ding_t
{
std::string dang;
} foo;
struct boom_t {
std::vector <ding_t> chuck;
} bar;
int main () {
vector <boom_t> tom;
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
//error C2661: 'erase' : no overloaded function takes 0 parameters
//tom.erase( );
// erase the 6th element
tom.erase (tom.begin()+5);
// erase the first 3 elements:
//tom.erase (tom.begin(),tom.begin()+3);
// erase everything:
//tom.erase (tom.begin(),tom.end() );
return 0;
}
Okay, I've done this little check, just to make sure. (Why didn't I think of this earlier... was quite late yesterday... ) The initial code was badly written and didn't work, apologies for that.
This:
#include <string>
#include <vector>
struct ding_t {
std::string dang;
} foo;
struct boom_t {
std::vector <ding_t> chuck;
} bar;
int main () {
std::vector <boom_t> tom;
while (true) {
tom.resize(10);
tom[4].chuck.resize(5);
tom[4].chuck[3].dang = "jerry";
tom.erase( tom.begin(), tom.end() );
}
return 0;
}
causes no memory leak, the used memory is stable.
Related
Following is my code snippet. I am trying to write generic function to check whether pointer is valid and deleting it.
#include <windows.h>
#include <vector>
#include <map>
#include <string>
using namespace std;
struct testStruct
{
int nVal;
_TCHAR tcVal[256];
testStruct()
{
wmemset(tcVal, 0, _countof(tcVal));
}
};
void deletePointer(void *obj)
{
if (obj)
{
delete obj;
obj = NULL;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
testStruct *obj = new testStruct;
wstring *strVal = new wstring();
vector<wstring> *vecVal = new vector<wstring>;
map<wstring,wstring> *mapVal = new map<wstring, wstring>;
//My business logic goes here.
//Finally after all business logic, clearing allocated memory.
deletePointer(obj);
deletePointer(strVal);
deletePointer(vecVal);
deletePointer(mapVal);
return 0;
}
While I am not facing any compilation or runtime error, just wanted to confirm, if this is the right way to check and delete multiple points. I don't want to check individual pointer whether it is valid or not before deleting. So calling generic function.
Thanks for your suggestions in advance.
Compilation and runtime errors are not present. Just need confirmation, if this is right way or is there a better way to do this.
No, it's both incorrect and unnecessary
If your compiler doesn't report error on this code, crank up warnings: https://godbolt.org/z/7ranoEnMa. Deleting a void* is Undefined Behaviour, you cannot predict what will be the result. If it's currently not crashing, it will likely crash at some random other use when you will least expect it.
It's unnecessary, because it's perfectly fine to delete nullptr; and your function only checks against that. If you wanted to check if the pointer is actually valid like Nathan Pierson suggests in comment (and you don't assign nullptr to them consistently), that's not possible. You are responsible for your memory management, no if can help if you don't do that correctly throughout the program.
And it's also not necessary, because memory management is already done for you. Containers shouldn't be ever allocated on the heap. Simply do
wstring strVal;
vector<wstring> vecVal;
map<wstring,wstring> mapVal;
And drop the pointers. C++ containers do all the magic by themselves and are generally small by themselves (sizeof(std::vector) is usually 3*sizeof(void*)).
Assuming you really need testStruct on the heap rather than in automatic storage, you should use a smart pointer:
std::unique_ptr<testStruct> obj = std::make_unique<testStruct>();
There, it's created, allocated on the heap and will be automatically deleted when obj ends its scope. You don't have to worry about deleteing anything anymore.
If you really want to have a function that deletes objects manually, it should look like this:
template <typename T>
void deletePointer(T*& obj)
{
delete obj;
obj = nullptr;
}
It keeps the type of the pointer to be deleted and updates passed pointer with nullptr, so it won't be invalid later on.
I’m a C++ beginner with a background in Python, Java, and JS, so I’m still learning the ropes when it comes to pointers.
I have a vector of shared pointers. Inside of a different function, I assign a shared pointer to a variable and add it to the vector. If I try to access the added element after that function exits, a segmentation fault happens:
class Bar
{
private:
std::vector<std::shared_ptr<Foo>> fooVector;
}
void Bar::addToFoo()
{
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
}
void Bar::otherMethod()
{
// this method gets called sometime after addToFoo gets called
…
fooVector[anIndex]->baz(); // segfaults
…
}
But, if push_back a shared pointer and not a variable, it works.
// this works:
fooVector.push_back(std::shared_ptr<Foo>(new Foo(…)));
// this segfaults:
std::shared_ptr<Foo> foo (new Foo(…));
fooVector.push_back(foo);
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong). How do you push_back a shared_ptr variable to a vector of shared_ptrs in C++?
Why Use A Variable
Though pushing shared_ptrs to vectors directly without variables works, I prefer to use variables in order to do this:
std::shared_ptr<Rider> rider;
switch (iProcessorModesParam)
{
case PEAKS_MODE:
rider = std::shared_ptr<Rider>(new PeaksRider(…));
break;
case RMS_MODE:
rider = std::shared_ptr<Rider>(new RMSrider(…));
break;
}
volumeRiders.push_back(rider);
PeaksRider and RMSrider are subclasses of Rider. I want to store all subtypes of Rider in the same vector of Riders. I learned that adding subtypes of Rider to a vector of Riders doesn’t work and pointers are needed in order to achieve this kind of polymorphism:
std::vector<Rider> // doesn’t work with subtypes
std::vector<*Rider>
std::vector<std::shared_ptr<Rider>>
Having the std::shared_ptr<Rider> rider; variable avoids repeating the .push_back(…) code for each type of Rider.
Instead of assigning shared pointer, user reset method.
rider.reset(new PeaksRider(…));
other that this, your code snippets seems to okay to me.
segfault may have caused because of the index variable ( which may be out of range). i suggest you to use .at(index) for accessing pointer from vector and wrap that part of code in a try..catch block and see what is the real error.
And regarding...
I believe it happens because the foo variable gets deleted when the addToFoo function exits (correct me if I’m wrong).
This is not true, share_ptrs use a local counter for #of references. as soon as you pushed the pointer to vector the counter gets incremented to 2 and event after control exits the function the counter is decremented to 1. so, your object is not destroyed yet.
There is no problem on creating a shared pointer instance, storing it in a variable, and doing a push_back to a vector after that. Your code should be fine as long as the index that you use when calling "otherMethod" is valid. However, I have a couple of suggestions for your code:
When you create a shared_ptr, it is highly recommended to do it through "std::make_shared" to ensure the safety and correctness of your code in all situations. In this other post you will find a great explanation: Difference in make_shared and normal shared_ptr in C++
When accessing positions of a vector using a variable that may contain values that would cause an out-of-bounds access (which usually leads to segmentation faults) it is a good practice to place asserts before using the vector, so you will detect these undesired situations.
I just wrote a small snippet that you can test to illustrate what I just mentioned:
#include <iostream>
#include <vector>
#include <memory>
#include <cassert>
class Foo
{
public:
int data = 0;
};
class Bar
{
public:
void addNewFoo(int d)
{
std::shared_ptr<Foo> foo(new Foo());
foo->data = d;
fooVector.push_back(foo);
}
void addNewFooImproved(int d)
{
auto foo = std::make_shared<Foo>();
foo->data = d;
fooVector.push_back(foo);
}
void printFoo(int idx)
{
assert(idx < fooVector.size());
std::cout << fooVector[idx]->data << std::endl;
}
private:
std::vector<std::shared_ptr<Foo>> fooVector;
};
int main()
{
Bar b;
b.addNewFoo(10);
b.addNewFoo(12);
b.addNewFooImproved(22);
b.printFoo(1);
b.printFoo(2);
b.printFoo(0);
}
This question already has answers here:
Does C++ support 'finally' blocks? (And what's this 'RAII' I keep hearing about?)
(16 answers)
Closed 6 years ago.
I am new to C++, coming from C#.
Here is the code :
void function(int n)
{
double* array = new double[n];
//some work that can return or throw an exception
//...
delete[] array;
return;
}
I know there is no C# using equivalent in C++.
Is there a simple and elegant way to ensure that memory will be released what ever happens ?
In C++, the code would look as follows:
#include <vector>
void function()
{
std::vector<double> array(100);
//some work that can return when or throw an exception
//...
return;
}
If you really don't want to initialize the array elements and don't need to resize the array and don't need iterators, you can also use:
#include <memory>
void function()
{
std::unique_ptr<double[]> array(new double[100]);
//some work that can return when or throw an exception
//...
return;
}
In both cases you access the array elements with array[0], array[1], etc.
Finally, if you don't need to transfer ownership of the data out of the function, know the size of the array at compile time, and the size isn't too large, you may also consider having a direct array object:
void function()
{
double array[100]; // uninitialized, add " = {}" to zero-initialize
// or:
std::array<double, 100> array; // ditto
//some work that can return when or throw an exception
//...
return;
}
Automatic variables are destroyed automatically at the end of scope, whether due to return or a throw:
{
double array[100];
throw 1; // no memory leaked
}
sorry for the misleading example, the size of the array is not known at compile time
In that case you do need a dynamic array. A popular solution to handling cleanup of resources such as dynamic memory is to wrap the pointer (or handle or descriptor depending on the type of resource) in a class, that acquires the resource on initialization, and releases on destruction. Then you can create an automatic variable of this wrapper type. This pattern is called "Resource acquisition is initialization" or RAII for short.
You don't need to write your own RAII wrapper for a dynamic array however. The standard library has you covered: std::vector
Hey..
I'm having trouble with some homework.
We are working on VectorList ( kinda like linked list but with vectors - don't ask why.. )
Anyway I have something like this:
#ifndef VECTORLIST_H
#define VECTORLIST_H
#include <iostream>
#include <vector>
using namespace std;
template< typename NODETYPE >
class VectorList
{
public:
VectorList(); // constructor
~VectorList(); // destructor
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
vector< NODETYPE > *vList; // list data as a vector
};
I need to fill in the functions.. my problem is that I do not understand how
to use STIL when I have *vList.. its a pointer to the first vector element?
// display contents of VectorList
template< typename NODETYPE >
void VectorList< NODETYPE >::print() const
{
// Fill in the missing code
}
My Idea was to use a for loop on the vector and use cout<< vector[i]<< endl;
to print the vector out..
Problem is that I get all sorts of errors and seg faults.
I do not understand how to access the vector in the function,
and how to access its elements.
This is a header file, and in the main we declare an object of VectorList<NODETYPE> IntVector...
So how can I do this?
Any help with understanding of how this *vList plays a role here would help a lot and
I'd probably be able to finish the rest..
Also, for isEmpty(), I assume I can use vList.empty().. but since vList is a pointer..
it doesn't work quite well.
== For the constructor/destructor what can I do?
I know for destructor I should iterate through the vector and use delete on each element.
But shoul
Please explain this to me, I am frustrated =[
my problem is that I do not understand how to use STL when I
have *vList.. its a pointer to the first vector element?
I assume that you are required as part of your homework to use pointer-to-vector instead of a vector itself. As a rule, I never use pointers-to-containers. In fact, the best thing that I discovered in switching from C to C++ was that I could write entire programs with no pointers at all, thanks to STL programming. Unless you are required to use pointer-to-vector, I recommend that you use the vector directly.
Certainly it is easier to use the vector proper than a pointer, but don't worry. Using the pointer isn't too bad.
First, in order to use a pointer-to-something, one must allocate the something. So, in your constructor, invoke new.
vList = new std::vector<NODETYPE>;
Anytime we invoke new, we must have a matching delete somewhere. Since our new is in our constructor, we need to invoke delete in the destructor:
delete vList;
You said:
but since vList is a pointer.. it doesn't work quite well.
Here is where life gets easy. Generally, if p is a pointer to some type, then (*p) is the object to which p points. Here are some examples:
int i = 1;
int *pInt = &i;
i = 4;
(*pInt) = 4;
std::cout << i << " " << (*pInt) << "\n";
std::vector<NODETYPE> v;
std::vector<NODETYPE> *pVector;
v.push_back();
(*pVector).push_back();
it = v.begin();
it = (*pVector).end();
So, invoking members of vList is easy : (*vList).empty().
So, your code might be :
void insertAtFront(const NODETYPE& node) { (*vList).push_front(node); }
There is a short-cut operator -> that makes the above somewhat easier to read:
void insertAtFront(const NODETYPE& node) { vList->push_front(node); }
The expression x->y is more-or-less equivalent (*x).y.
To sum up:
Allocate your vList in your constructor with new. Destroy your vList in your destructor with delete. Invoke members of vList using either (*vList).function() or vList->function().
Good luck, and come back if you have other questions!
P.s. Since you have a non-trivial destructor, you'll need to consider the rule of three.
P.P.s. You said something about iterating the vector in your destructor and deleting each of the objetcs you find there. You would only need to do that if your data type were vector-of-pointers-to-NODETYPE (contrast to what you declared: pointer-to-vector-of-NODETYPE). Until and unless you become completely comfortable with pointers, I recommend that you never store pointers in STL containers.
You should construct your object in the constructor (if you really need using bare pointers): vList = new vector< NODETYPE >();, free memory in the destructor: delete vList;, translate your methods to corresponding methods of the container class. For example, insertAtBack would be implemented as vList->push_back(elem);
Just wondering, because of a problem I am running into, is it possible to create a vector of pointers? And if so, how? Specifically concerning using iterators and .begin() with it, ie: How would I turn this vector into a vector of pointers:
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer
for(citer=cvect.begin();citer<cvect.end();citer++)
{
citer->func();
}
Sure.
vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
(*citer)->func();
}
Things to keep in mind:
You'll need to cleanup after your self if you use dynamically allocated memory as I did in my example
e.g.:
for(...) { delete *i; }
This can be simplified by using a vector of shared_ptrs (like boost::shared_ptr). Do not attempt to use std::auto_ptr for this, it will not work (won't even compile).
Another thing to keep in mind, you should avoid using < to compare iterators in your loop when possible, it will only work for iterators that model a random access iterator, which means you can't change out your code to use e.g. a std::list.
vector <c> cvect is not a vector of pointers. It is a vector of objects of type c. You want vector <c*> cvect. and the you probably want:
cvect.push_back( new c );
And then, given an iterator, you want something like:
(*it)->func();
Of course, it's quite probable you didn't want a vector of pointers in the first place...
Yes it is possible, and in fact it is necessary to use pointers if you intend your vector to contain objects from an entire class hierarchy rather than of a single type. (Failing to use pointers will result in the dreaded problem of object slicing -- all objects are silently converted to base class type. This is not diagnosed by the compiler, and is almost certainly not what you want.)
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c*> cvect; // Note the type is "c*"
cvect.push_back(&cobj); // Note the "&"
vector<c*>::iterator citer;
for(citer=cvect.begin();citer != cvect.end();citer++) // Use "!=" not "<"
{
(*citer)->func();
}
Note that with a vector of pointers, you need to do your own memory management, so be very careful -- if you will be using local objects (as above), they must not fall out of scope before the container does. If you use pointers to objects created with new, you'll need to delete them manually before the container is destroyed. You should absolutely consider using smart pointers in this case, such as the smart_ptr provided by Boost.
Yes, sure.
// TestCPP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
class c
{
public:
void virtual func() = 0;
};
class sc:public c
{
public:
void func(){cout<<"using func";}
};
int _tmain(int argc, _TCHAR* argv[])
{
sc cobj;
vector<c*> cvect;
cvect.push_back(&cobj);
vector<c*>::iterator citer;
for(citer=cvect.begin();citer<cvect.end();citer++)
{
(*citer)->func();
}
return 0;
}
Please note the declaration of vector<c*> cvect and the use of cvect.push_back(&cobj).
From the code provided, you are using iterator in a wrong way. To access the member an iterator is pointing to you must use *citer instead of citer alone.
You have create vector<c*> for a vector of pointers. Then use new to allocate the memory for c objects and push them into vector. Also, don't forget that you have to delete yourself and vector.clear() will not release the memory allocated for c objects. You have to store c as a vector of pointers here, otherwise the call to the virtual function will not work.
Try Boost Pointer Container Library. It has several advantages over regular vector of pointers, like:
my_container.push_back( 0 ); // throws bad_ptr
ptr_vector<X> pvec;
std::vector<X*> vec;
( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
pvec.begin()->foo(); // no indirection needed