I am trying to grasp the pointers in C++ but I can't find the answer to these questions.
If I was to have an ArrayList in Java and I wanted to add new Objects to it in a loop I would do something like:
ArrayList<MyObject> list = new ArrayList<MyObject> ();
for (int i = 0; i < otherList.length; i++) {
list.add(i, new MyObject(otherList.get(i)));
}
But let's say I wanted to do the same thing in C++ using vectors. I have found two methods:
vector<MyObject> vector;
for (auto i = otherVector.begin(); i != otherVector.end(); i++) {
// do this
vector[i - otherVector.begin()] = * new MyObject(*i);
// or this
MyObject newObj(*i);
vector[i - otherVector.begin()] = newObj;
}
What is the difference between those 2 methods and if I use the second one, do I need to manually delete the pointers from the list? If I were to use the second method with smart pointers, would they be automatically deleted by the gc when the vector was not used anymore?
The first method creates a memory leak. There's no saving it. Forget you ever heard of operator new.
if I use the second one, do I need to manually delete the pointers from the list?
There are no pointers in the list.
The second would work, and it would clean up after itself when vectorgoes out of scope. But do not do that either.
vector<MyObject> vector;
for (auto i = otherVector.begin(); i != otherVector.end(); i++) {
// do this
vector[i - otherVector.begin()] = * new MyObject(*i); // No, no, no, no.
// or this
MyObject newObj(*i);
vector[i - otherVector.begin()] = newObj; // Please don't.
}
But here's one way it should be done. No loop. (And don't name things "vector".)
std::vector<my_object> vec(other_vector);
If you're really into the brevity thing, do this:
auto vec{other_vector};
Related
here is an example of a code hopefully will demonstrate my confusion
#define MAX_LENGTH 5
class Bar
{
private:
Foo *_myFooArray[MAX_LENGTH];
public:
Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
_myFooArray[i] = new Foo(i);
}
}
};
Since I am not creating the array with new I don't think I can use delete[] but what if I want to delete the objects that are allocated dynamicly? do I iterate through the array and delete them one at a time? as such;
~Bar()
{
for (int i = 0; i < MAX_LENGTH; ++i)
{
delete _myFooArray[i];
}
}
I will probably hear some of you screaming at me Use Vectors!! I appreciate that. I just want to learn. Just for completeness, If for some reason I have to use the array as mentioned above, are there anything that I need to pay extra attention besides deleting the array correctly?
One of the rules in C++ when not using smart pointers is "every new needs a delete."
You must use the destructor from your question to avoid leaking memory. The array itself is not allocated using new so you do not need to delete it.
No, you do not delete [] the array. The array is part of your instance's data. The elements you allocate specifically are not, so you should delete them.
There are legacy functions that need a dynamic array A**. For example,
A** array = new A*[100];
foo(array, 100);
...
void foo(A** a, int len) {
for(int i=0;i<len; ++i) {
a[i] = A::create(...);
}
}
I was wondering if I could use any "smart" pointers to manage this array.
I could use boost::scoped_array array. Its array.get() returns A**, and so it can work with legacy functions. But I think the destructor of array only free the top-level pointers, but not the second-level.
ptr_vector automatically deletes everything. But it does not have a way to return A**.
Do we have any other solutions?
If the API creates the objects using a call like A::create(...) which returns a pointer, then surely the API has a complementary call to destroy the objects such as A::destroy(ptr). In that case, the following custom deleter should be appropriate:
std::unique_ptr<A*, void(*)(A**)> array_ptr(
new A*[100],
[](A** ptr) {
for(std::size_t i = 0; i < 100; i++)
A::destroy(ptr[i]);
delete[] ptr;
}
);
foo(array_ptr.get(), 100);
EDIT I rewrote my answer, since the first version seemed to have been way off.
I created a class and using multi-dimensional pointer as follows:
variable **v_mod;
v_mod = new variable *[3];
for(int i=0;i<3;i++)
{
v_mod[i] = new variable [n];
}
and deleting pointer after using
for( int i = 0 ; i < 3 ; i++ )
{
delete [] v_mod[i];
}
delete [] v_mod;
This is working perfectly fine but I am using many pointers. So can anyone help in writing a function in the class which helps in creating and deleting the pointers like
variable ** v_mod;
v_mod.create(3,n);
v_mod.delete();
and which works same way?
Don't use new use a vector:
vector<vector<variable>> v_mod(3, vector<variable>(n));
This will require that your variable object has a generated or your own default constructor.
But other than that you can use the vector version of v_mod as you used the dynamically allocated array version, except that a vector cleans itself up when it goes out of scope. So no need to delete.
EDIT:
#Hamza Anis has asked me how to do this without vector, so I'm updating this answer to reflect a couple ways to do that. Let me preface this by saying, vector is the right way to do this, anything short of vector is simply making life harder on everyone who handles the code.
Option 2 unique_ptr:
unique_ptr<variable[]> v_mod[3];
for(auto& i : v_mod) {
i = make_unique<variable[]>(n);
}
Option 3 only do this if it's a homework assignment:
variable* v_mod[3];
for(auto& i : v_mod) {
i = new variable[n];
}
for(auto& i : v_mod) {
delete[] i;
}
[Complex Example using ints]
Lets say i have a class like this:
class LolClass {
LPWSTR* stuff;
LolClass::LolClass(LPWCHAR lols) {
stuff = new LPWSTR[100];
for (int i = 0; i < 100; i++) {
stuff[i] = new wchar_t[wcslen(lols)+1];
wcsncpy(stuffs[i], lols, wcslen(lols)+1);
}
}
LolClass::~LolClass() {
delete[] stuff;
}
}
so if i call
LolClass* veryfunny = new LolClass(L"lol!");
it would make me 100 lol's, problem is when i call
delete veryfunny;
it deletes the pointer array but not the individual wchar_t's, if i try and loop through the wchar_t's and delete them then i just crash and i dont know what to do since i know for fact that they are still there even after i delete veryfunny (i checked by passing one of the pointers outside the class)
Thanks!
If you call
LolClass* veryfunny = new LolClass(L"lol!");
then you will eventually need to call:
delete veryfunny;
But for arrays, you need delete[]: stuff[i] = new wchar_t[n]; delete [] stuff[i];
In your code, you need to first loop over stuff and delete[] the elements, and then delete[] the array stuff itself.
Or just use a std::vector<std::wstring>.
Update: From what I understand, you're not actually worried about deleting *veryfunny, but rather about how to write a correct destructor for LolClass. Note that the destructor also gets invoked for global and automatic objects, e.g. { LolClass x(L"hello"); } /* boom */, so it doesn't really matter how you instantiate an object for LolClass. You have to get the class right in any case.
David Schwartz wins after all, the wchar's didnt let themselves be deleted because they werent null terminated
I want to create a number of objects of a class, but this number won't be known until runtime. Intuition tells me that I should use the following loop to create my objects:
for (int count = 0; count < no_of_objects; count ++)
{
ClassName object_name[count]
}
This, however does not work as the compiler doesn't appear to like using variables as object names. Is there a way I can create these objects using a loop, or do I have to use some other method.
Please bear in mind that I have not been using C++ for long and have only recently been introduced to programming, so my knowledge of the language is somewhat limited - so far, the array is the only data structure I have been taught - no vectors, etc.
It's time to learn vectors:
std::vector<ClassName> objects (no_of_objects);
Now use objects[0] through objects[no_of_objects - 1]; note that objects.size() equals no_of_objects. When you're ready, look at vector's methods, etc., but for now, this plus knowing the header to include (<vector>) is enough to use objects as a dynamic array.
In C++ you will have to allocate this dynamically if you do not know the number of objects until runtime. You would need code similar to this:
ClassName* pmyClasses = new ClassName[no_of_objects];
This will allocate an array to hold your class objects, you then need to initialize them.
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i] = new ClassName();
}
You can then access them via the array indexer:
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i].SomeFunction();
}
An important thing to note here is that if you use new to allocate memory, then you need to use delete to deallocate it. Since this is an array declaration then you need to use the delete [] operator.
for (int i=0; i < no_of_objects; i++)
{
delete pmyClasses[i];
}
delete [] pmyClasses;
If you are using this inside or a class it would be important to have the delete in the destructor of the class:
class UsingMyClass
{
private:
ClassName* pmyClasses;
public:
UsingMyClass(int no_of_objects)
{
pmyClasses = new ClassName[no_of_objects];
for (int i=0; i < no_of_objects; i++)
{
pmyClasses[i] = new ClassName();
}
}
~UsingMyClass()
{
for (int i=0; i < no_of_objects; i++)
{
delete pmyClasses[i];
}
delete [] pmyClasses;
}
}
By doing this, when the UsingMyClass object goes out of scope (assuming it was not created via a call to new or malloc) then the array of ClassName objects will be cleaned up.
If your class has a default constructor (and you want to default construct the instances), you can use an array new i.e. new ClassName[some_number] - which is of type ClassName*).
If it doesn't have a default constructor, you can fool around with placement new, or use an array of pointers and new each one manually.
TO allocate the memory dynamically you have to use the new keyword
ClassName = new object_name[count];
and make sure to delaocate the memory after by using delete keyword