1

In this code, an array of pointers newData is created in a for loop then it is pushed into a vector testData. The pointers are stored in the vector std::vector<testData*>.

My concern is that I need to make sure that the objects referenced by the pointers remain valid while the vector holds a reference to them. Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?

I mainly want to avoid copying the objects with a push_back.

How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?

int numFrames = 25;
int frameSize = 100;

std::vector<unsigned char*> testData;

unsigned char *newData;

for (int i = 0; i < numFrames; i++) {
    newData = new unsigned char[frameSize];

    for (int j = 0; j < frameSize; j++) {
        newData[j] = 'a'; // fill the frame with random data, 'a' here
    }

    testData.push_back(newData);
    newData = 0; // ??
    memset(&newData, 0, frameSize); // ??
}

std::cout << " testData " << testData.size() << "\n";
anastaciu
  • 23,467
  • 7
  • 28
  • 53
Moe
  • 382
  • 4
  • 10
  • 2
    does this code look fine? This completely depends on what it is supposed to do. I would say no, because I don't think it is necessary to use raw pointers – 463035818_is_not_an_ai Oct 26 '20 at 11:31
  • 2
    `memset(&newData, 0, frameSize);` doesn't seem right at all. – anastaciu Oct 26 '20 at 11:32
  • 2
    please don't spam tags. The `c++11` and `c++14` tags are for questions specifically about that c++ standard. If you compile with the current standard tagging `c++` is sufficient, if you depend on an older one, tag only that – 463035818_is_not_an_ai Oct 26 '20 at 11:33
  • 2
    No, this does not look fine. The memset will result in, pretty much, a guaranteed crash. – Sam Varshavchik Oct 26 '20 at 11:33
  • So how can I create an array of 'unsigned char*' of random char (here I just use 'a') and then push these arrays to a vector? – Moe Oct 26 '20 at 11:37
  • 1
    Why exactly are you not using (a) `std::vector`, or (b) `std::vector>`, or, if `frameSize` is a compile-time known constant, (c) `std::vector>` ? in short, *why do you think you need raw pointers in that vector?* Unless you can fathom a compelling reason, odds are strong *you don't need to do that*, and one of the options I mentioned is either viable, or even optimal, for your needed workflow. And you seem to be under the impression pointers are natively reference counted in C++; they're *not*. – WhozCraig Oct 26 '20 at 12:12

1 Answers1

2

Do I lose this reference by calling the line newData = new unsigned char[frameSize]; in a for loop?

No, if done correctly it's perfectly feasible.

The are some problems in your code though, in the line memset(&newData, 0, frameSize); // ?? you're setting the memory occupied by a pointer, which is usually no more than 8 bytes (depending on the architecture) with a size of 100 bytes, this invokes undefined behavior. You may wanted:

memset(&newData, 0, sizeof newData); // ??

But this wouldn't do what you need, nullifying the pointer would make you lose access to the data, you don't want that, and you are pushing the same pointer to the vector in each iteration, you'll end up with a vector filled with the same pointer pointing to the same data.

Moving its declaration inside the for loop would solve this. You're not copying any data, instead pushing a new pointer, pointing to a new memory location, into the vector, at each new iteration.

How can I create an array of unsigned char* of random char (here I just use 'a') and then push these arrays to the vector?`

Your code should look something like this:

Live demo

#include <iostream>
#include <vector>
#include <ctime>
int main()
{   
    srand(time(0)); //seed, not the best randomizer but does the job here
    
    const size_t numFrames = 25; //sizes can/should be constant and unsigned
    const size_t frameSize = 100;

    std::vector<unsigned char *> testData;

    for (size_t i = 0; i < numFrames; i++)
    {
        //in each iteration a new pointer
        unsigned char *newData = new unsigned char[frameSize];

        for (size_t j = 0; j < frameSize; j++)
        {
            newData[j] = 'a' + rand() % 26; //random alphabetic char
        }
        testData.push_back(newData);
    }
    
    std::cout << "testData " << testData.size() << "\n";        
    
    for (size_t i = 0; i < numFrames; i++) //test print
    {
        for (size_t j = 0; j < frameSize; j++)
        {
            std::cout << testData[i][j];
        }
        std::cout << "\n";
    }
}

Needless to say you should delete the memory you previously allocated when you no longer need it.

If you want a better random engine you can check this post Generate random numbers using C++11 random library.

Some notes:

As you're probably aware the data pointed by newData pointers can't be treated as a string, aka, a null terminated char array because, of course, they're not null terminated.

You'll need to manually manage the memory you allocated, that is to say that the memory reserved manually will also have to be deleted manually, when you're done with it.

The code corrections are for your code as it is, but as WhozCraig correctly points out, you would probably be better off using STL containers all around instead of pointers.

anastaciu
  • 23,467
  • 7
  • 28
  • 53
  • Thanks for your comments! Just to add that I use the vector `testData` later, so my concern is that can I call `unsigned char *newData = new ....` in the loop? Will the pointers that I push in the vector be affected by this call? – Moe Oct 26 '20 at 12:03
  • @MohammedZiad, the answer to your question, yes you can, `newData` will be treated as a different pointer, pointing to a different memory location at each new iteration. Each vector element will have a different pointer to different data, no copies. Check my answer, it shoud solve your problems – anastaciu Oct 26 '20 at 12:45