1

With this code:

#include <iostream>
#include <vector>
#include <stdio.h>

struct x
{
    int a;
    const char* t;
};

int main()
{
    std::vector<x> instances;
    
    while(true)
    {
        printf("wait for key1\n");
        getchar();
        getchar();
        
        {
            for(int i = 0; i < 100000; i++)
            {
                x n;
                n.a = i;
                n.t = "x instance";
                instances.push_back(n);
            }
            //x instance deleted right?
        }
        
        {
            x x1, x2, x3;
            x1 = instances[0];
            x2 = instances[1];
            x3 = instances[2];
            
            std::cout << x1.t << std::endl;
            std::cout << x2.t << std::endl;
            std::cout << x3.t << std::endl;
            
            instances.clear();
        }
        
        printf("wait for key2\n");
        getchar();
        getchar();
    }
    
    return 0;
}

I'm getting this output:

wait for key2
wait for key1
x instance
x instance
x instance

That's cute but I think I should get a output like this:

wait for key2
wait for key1
>>£#$@@#£#$½£#$½
>>£#$@@#£#$½£#$½
>>£#$@@#£#$½£#$½

Because x struct instances must be deleted. Am I wrong? And the true implemention should be like this:

#include <iostream>
#include <vector>
#include <stdio.h>

struct x
{
    int a;
    const char* t;
};

int main()
{
    std::vector<x*> instances;
    
    while(true)
    {
        printf("wait for key1\n");
        getchar();
        getchar();
        
        {
            for(int i = 0; i < 100000; i++)
            {
                x* n = new x();
                n->a = i;
                n->t = "x instance";
                instances.push_back(n);
            }
        }
        
        {
            x* x1 = 0;
            x* x2 = 0;
            x* x3 = 0;
            x1 = instances[0];
            x2 = instances[1];
            x3 = instances[2];
            
            std::cout << x1->t << std::endl;
            std::cout << x2->t << std::endl;
            std::cout << x3->t << std::endl;
            
            instances.clear(); /* delete x instances one-by-one like 'delete instances[i];' */
         }
        
        printf("wait for key2\n");
        getchar();
        getchar();
    }
    
    return 0;
}

I'm not clear about memory management. Why I can still get (non-new'd) 'x instances' after cleanup? Examples?

I've looked in link>> and I think x instances in the for loop must be deleted?

Update

Here is my example implementation for other people (beginners like me). I'll use a sync'd queue for socket io packets and I don't care about thread.join() just because my threads are only workers, not managers! (what a real-life simulation!)

#include <iostream>
#include <thread>
#include <chrono>

bool b1 = true;
bool b2 = true;
//Of course you can create only 1 boolean for all threads (isAlive should be a good name for it)
//but this way provides more detailed thread aliveness control.

void process(bool* ref, int id)
{
    bool my = *ref;
    while (my)
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "thread#" << id << std::endl;
        my = *ref;
    }
    std::cout << "thread#" << id << " end." << std::endl;
}

int main()
{
    std::thread(process, &b1, 0).detach();
    std::thread(process, &b2, 1).detach();

    std::cin.get();
    b1 = false;
    
    std::cin.get();
    b2 = false;
    
    //MS-DOS :(
    std::cin.get();

    return 0;
}

Posibble output:

thread#thread#10
thread#0
thread#1
thread#1
thread#0
//Hit the enter!
thread#1
thread#0
thread#0 end.

thread#1 thread#1 //Hit the enter! thread#1 thread#1 end. //Hit the enter!

Community
  • 1
  • 1
PilawyerDev
  • 271
  • 2
  • 14

5 Answers5

3

When you add an element to vector with push_back, the element is copied into the vector. This means that the vector has its own copy of your element, and even if the element is deleted (either by you or by the end of the scope), the vector still contains the element. When the vector is deleted, the vector takes care of deleting its elements one by one, all by itself, so you don't have to.

You can find more information about push_back here:

Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.

Your "improved" version, where you dynamically allocate the variables, is a misuse of pointers. If all you're doing is inserting the elements into the vector then there's no need to dynamically allocate them, because the vector won't even contain the dynamically allocated values - only copies of them.

Daniel Kleinstein
  • 1,718
  • 13
  • 19
  • That's cool, how to remove the instance completely? Edit: And when I need to allocate dynamically? Namely when I can't get x instances from vector? – PilawyerDev Jul 03 '14 at 11:12
  • 1
    @PilawyerDev See [that](https://blog.uraniborg.net/post/delete-a-c-plus-plus-list-of-pointers-like-a-boss/) to clear a list of pointers and delete them. – Unda Jul 03 '14 at 11:14
1

You are putting a copy into the vector.

for(int i = 0; i < 100000; i++)
{
    x n;
    n.a = i;
    n.t = "x instance";
    instances.push_back(n); // <--- Copy of n is created and added to instances
}
Stormenet
  • 23,672
  • 8
  • 50
  • 65
0

When you do push_back, you insert the copy of your instance into the vector. So it does not matter that the original instance has been deleted. The strings are going to be lost, probably, because they were allocated locally and the original string was destroyed.

Regarding the strings not being deleted, it might be due to the fact that you assign a static string to the pointer. Try the same with the string which you create dynamically.

Ashalynd
  • 11,728
  • 2
  • 29
  • 35
0

Nop, it shouldn't be deleted.

When you call push_back() on a vector, you are creating a copy of x inside the vector.

nasser-sh
  • 3,343
  • 13
  • 25
0

std::vector::clear() does not delete items, instead it calls any appropriate destructor. The elements of instances are pointers and there is no globally applicable destructor. While you might think that deletion is an appropriate behaviour std::vector::clear() has no idea who might own these these pointers. In general if you allocated the memory you should free it. Try

for( std::vector<x*>::iterator it=instances.begin(); it!=instances.end(); ++it)
{
    delete *it;
}
instances.clear();
dyspraxia
  • 16
  • 3