I've been reading through some books, and when it comes to Class/Functions using Pointers/Dynamic Memory (or heap or w/e they call it) I start to get confused.
Does anyone have a simple....like easy example they can show, because the books im using are using overly complex examples (large classes or multiple functions) and it makes it hard to follow. Pointers have always been my weak point anyways but I understand BASIC pointers, just classes/functions using them is a little bit confusing.
Also.....when would you use them is another question.
Stack allocation:
char buffer[1000];
Here the 1000 must be a constant. Memory is automatically freed when buffer goes out of scope.
Heap Allocation:
int bufsz = 1000;
char* buffer = new char[bufsz];
//...
delete [] buffer;
Here bufsz can be a variable. Memory must be freed explicitly.
When to use heap:
You don't know how much space you will need at compile time.
You want the memory/object to persist beyond the current scope.
You need a large chunk of memory (stack space is more limited than heap space)
Your computer's RAM is a big pile of bytes ordered one after another, and each one of those bytes can be accesed independently by it's address: an integer number startig from zero, upwards. A pointer is just a variable to hold that address of a single place in memory.
Since the RAM is a big chunk of bytes, the CPU ussually divides that big pile of bytes on several chunks. The most important ones are:
Code
Heap
Stack
The Code chunk is where the Assembly code lies. The Heap is a big pool of bytes used to allocate:
Global variables
Dynamic data, via the new operation on C++, or malloc() on C.
The stack is the chunk of memory that gets used to store:
Local variables
Function parameters
Return values (return statement on C/C++).
The main difference between the Stack and Heap is the way it is used. While the Heap is a big pool of bytes, the Stack "grows" like a stack of dishes: you can't remove the dish on the bottom unless there are no more dishes on it's top.
That's how recursion is implemented: every time you call a function recursively, memory grows on the stack, allocating parameters, local variables and storing return values of the returning functions, one on top of the others just like the stack of dishes.
Data living on the Stack have different "Life Span" than the data living on the Heap. Once a function exits, the data on the local variables get lost.
But if you allocate data on the Heap, that data won't get lost util you explicitly free that data with the delete or free() operations.
A pointer is basically a variable that contains the memory address of another variable (or in other cases to a function, but lets focus on the first).
That means that if I declare int[] x = {5,32,82,45,-7,0,123,8}; that variable will be allocated to memory at a certain address, lets say it got allocated on address 0x00000100 through 0x0000011F however we could have a variable which indicates a certain memory address and we can use that to access it.
So, our array looks like this
Address Contents
0x00000100 1
0x00000104 32
0x00000108 82
0x0000010B 45
0x00000110 -7
0x00000114 0
0x00000118 123
0x0000011B 8
If, for example, we were to create a pointer to the start of the array we could do this: int* p = &x; imagine this pointer variable got created a memory address 0x00000120 that way the memory at that address would contain the memory location for the start of array x.
Address Contents
0x00000120 0x00000100
You could then access the contents at that address through your pointer by dereferencing the pointer so that int y = *p would result in y = 1. We can also move the pointer, if we were to do p += 3; the pointer would be moved 3 addresses forward (note, however, that it moves 3 times the size of the type of object it is pointing to, here I am making examples with a 32 bit system in which an int is 32 bits or 4 bytes long, therefore the address would move by 4 bytes for each increment or 12 bytes in total so the pointer would end up pointing to 0x0000010B), if we were to dereference p again by doing y = *p; then we'd end up having y = 45. This is just the beginning, you can do a lot of things with pointers.
One of the other major uses is to pass a pointer as a parameter to a function so that it can do operations on certain values in memory without having to copy all of them over or make changes that will persist outside of the function's scope.
Warning: Don't do this. This is why we have vectors.
If you wanted to create an array of data, and return if from a function, how would you do it?
Obviously, this does not work:
int [10] makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
You cannot return an array from a function. We can use pointers to refer to the first element of an array, like this:
int * makeArray(int val)
{
int arr[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return &(arr[0]); // Return the address of the first element.
// Not strictly necessary, but I don't want to confuse.
}
This, however, also fails. arr is a local variable, it goes on the stack. When the function returns, the data is no longer valid, and now you have a pointer pointing to invalid data.
What we need to do is declare an array that will survive even after the function exits. For that, we use keyword new which creates that array, and returns the address to us, which needs to be stored in a pointer.
int * makeArray(int val)
{
int * arr = new int[10];
for(int i=0; i<10; ++i)
arr[i] = val;
return arr;
}
Then you can call that function and use that array like this:
int * a = makeArray(7);
for(int i=0; i<10; ++i)
std::cout << a[i] << std::endl;
delete [] a; // never forget this. Obviously you wouldn't do it right
// away like this, but you need to do it sometime.
Using pointers with new also gives you the advantage that you can determine the size of the array at runtime, something you can't do with local static arrays(though you can in C):
int * makeArray(int size, int val)
{
int * arr = new int[size];
for(int i=0; i<size; ++i)
arr[i] = val;
return arr;
}
That used to be one of the primary purposes for pointers. But like I said at the top, we don't do that anymore. We use vector.
One of the last vestiges of pointers is not for dynamic arrays. The only time I ever use them, is in classes where I want one object to have access to another object, without giving it ownership of that object. So, Object A needs to know about Object B, but even when Object A is gone, that doesn't affect Object B. You can also use references for this, but not if you need to give Object A the option to change which object it has access to.
(not tested, just writing down. and keeping things intentionally primitive, as requested.)
int* oneInt = new int; // allocate
*oneInt = 10; // use: assign a value
cout << *oneInt << endl; // use: retrieve (and print) the value
delete oneInt; // free the memory
now an array of ints:
int* tenInts = new int[10]; // allocate (consecutive) memory for 10 ints
tenInts[0] = 4353; // use: assign a value to the first entry in the array.
tenInts[1] = 5756; // ditto for second entry
//... do more stuff with the ints
delete [] tenInts; // free the memory
now with classes/objects:
MyClass* object = new MyClass(); // allocate memory and call class constructor
object->memberFunction("test"); // call a member function of the object
delete object; // free the object, calling the destructor
Is that what you wanted? I hope it helps.
I think this is what you're asking about:
Basically C++ doesn't allow variable-sized arrays. Any array in C++ has to be given a very specific size. But you can use pointers to work around that. Consider the following code:
int *arry = new int[10];
That just created an array of ints with 10 elements, and is pretty much the same exact thing as this:
int arry[] = int[10];
The only difference is that each one will use a different set of syntax. However imagine trying to do this:
Class class:
{
public:
void initArry(int size);
private:
int arry[];
};
void class::initArry(int size)
{
arry = int[size]; // bad code
}
For whatever reason C++ was designed to not allow regular arrays to be assigned sizes that are determined at runtime. Instead they have to be assigned sizes upon being coded. However the other way to make an array in C++ - using pointers - does not have this problem:
Class class:
{
public:
~class();
void initArry(int size);
private:
int *arry;
};
class::~class()
{
delete []arry;
}
void class::initArry(int size)
{
arry = new int[size]; // good code
}
You have to do some memory cleanup in the second example, hence why I included the destructor, but by using pointers that way you can size the array at runtime (with a variable size). This is called a dynamic array, and it is said that memory here is allocated dynamically. The other kind is a static array.
As far as 2-dimensional arrays go, you can handle it kind of like this:
Class class:
{
public:
~class();
void initArrays(int size1, int size2);
private:
int **arry;
};
class::~class()
{
delete [] arry[0];
delete [] arry[1];
delete [] arry;
}
void class::initArrays(int size1, int size2)
{
arry = new int*[2];
arry[0] = new int[size1];
arry[1] = new int[size2];
}
Disclaimer though: I haven't done much with this language in a while, so I may be slightly incorrect on some of the syntax.
Related
here is the class that I am using.
#include<stdio.h>
#include <string.h>
class EnDe{
private:
int *k;
char *temp;
public:
char * EncryptString(char *str);
char * DecryptString(char *str);
EnDe(int *key);};
EnDe::EnDe(int *key){
k=key;
}
char * EnDe::EncryptString(char *str){
int t=2;
t=(int)k[1]*(int)2;
for (int i=0;i<strlen(str);i++){
temp[i]=str[i]+k[0]-k[2]+2-k[1]+k[3]+t;
}
char alp=k[0]*57;
for (int y=strlen(str);y<strlen(str)+9;y++){ //--*
temp[y]=alp+y; //--*
}
temp[(strlen(str)+9)]='\0'; //--*
return temp;
}
char * EnDe::DecryptString(char *str){
int t=2;
t=k[1]*2;
for (int i=0;i<strlen(str);i++){
temp[i]=str[i]-t-k[3]+k[1]-2+k[2]-k[0];
}
temp[(strlen(str)-9)]='\0';
return temp;
}
And here is the main program.
#include <stdio.h>
#include "EnDe.h"
int main(void){
char *enc;
char op;
printf("\nE to encrypt and D to decrypt");
int opi[4]={1,2,9,1};
EnDe en(opi);
strcpy(enc,en.EncryptString("It is C's Lounge!! "));
printf("Encrypted : %s",enc);
return 0;
}
Something is wrong with en.EncryptString function
when I run the program it stops working giving error and on removing strcpy(enc,en.EncryptString("It is C's Lounge!! ")); it runs. I want this problem to be resolved.
char *enc;
strcpy(enc,en.EncryptString("It is C's Lounge!! "));
You don't provide any space for the copy - enc doesn't point anywhere.
You never allocate any memory.
When you say
char *foo;
You tell the compiler that you want to store a memory address to some data somewhere, but not that you also want to store some data. Your class stores two pointers (int *k and char *temp) that never get any memory assigned to them, and so does your main function with char *enc. This can never work.
In C and C++, there are two modes of memory allocation: one is stack-based allocation, where you declare variable names in a function, and the compiler or the runtime will automatically allocate and release memory for you; the other is heap-based allocation, where you use malloc or new to allocate memory at run time, and must manually release that memory again with delete or free.
A pointer is "just" a stack-allocated variable that contains the address of another memory location. If you don't assign any value to a pointer, it points to invalid memory, and whatever you try to do with it will fail. To fix your program, you must make sure that every pointer points to valid memory. If you want it to point to a stack-based variable, you use the address-of operator:
int val = 4;
int *pointer_to_val = &val;
/* the pointer_to_val variable now holds the address of the val variable */
If you don't want it to point to a stack-allocated variable, you must allocate the memory yourself.
In C++, heap memory is allocated with the new operator, like so:
ClassType *instance = new ClassType(arg1, arg2)
where ClassType is the type of the class you're creating an instance of, instance is the pointer where you want to store the address of the instance you've just created, and arg1 and arg2 are arguments to the ClassType constructor that you want to run.
When you no longer need the allocated memory, you use delete to release the memory:
delete instance;
Alternatively, you can also use the C-style malloc and free functions. These are not operators; they are functions which return the address of the allocated memory. They do not work for C++ class instances (since you do not run the constructor over the returned memory), but if you want to run a pure-C program, they're all you have. With malloc, you do as follows:
char* string = malloc(size);
where string is the pointer for which you want to allocate memory, and size is the number of bytes you want the system to allocate for you. Once you're ready using the memory, you release it with free:
free(string);
When calling delete or free, it is not necessary to specify the size of the object (the system remembers that for you). Note, however, that you must make sure to always use delete for memory allocated with new, and to always use free for memory allocated with malloc. Mixing the two will result in undefined behaviour and possibly a crash.
I spend a lot of time trying to find out why I have an assert in this code.
If there is no destructor in the class, it's work well.
Can you explaine, why I have an Assert whit the class containing destructor.
I dont want to know the number of element in the array. I Just want to understand the Assert when there is a destructor in the class.
With Visual C++, the "new" call the "malloc" function.
=====================================================================================
More detail:
With: CTheClass* pArrayTheClass = new CTheClass[1];
In debug, in the _heap_alloc_dbg_impl() function,
you can find the following line of code:
blockSize = sizeof(_CrtMemBlockHeader) + nSize + nNoMansLandSize;
where:
sizeof(_CrtMemBlockHeader) : 32
nSize : 4
nNoMansLandSize : 4
After that, the memory is allocated (withHeaderBlock),
and the function return the pointer to the data part.
And at the end of "operator new[] " in the "new2.cpp" file,
this data pointer is return, to the program allocation.
But
With:
CTheClassWithDestructor* pArrayTheClassWithDestructor = new CTheClassWithDestructor[1];
is nearly the same thing...
but the nSize is equal to 8; sizeof( int) + 4 bytes
But this time, even if at the end of "operator new[] we have the dataPart pointer.
In the main program I receive this pointer with an offset of 4.
And if I substract 4 from the pointer there is no assert when I call the _msize() function.
That explain the Assert.
The assert is cause bt this offset of 4.
But why we have this offset of 4 ?
Conclusion
This offset of 4 bytes contain the number of element.
If the class have a destructor, the compiler reserve 4 bytes to hold the number of elements in the array.
If there is no destructor to call, we don't have this extra 4 bytes as offset.
Thank's
Marc
#include <malloc.h>
class CTheClass
{
private:
int TheValue_;
};
class CTheClassWithDestructor
{
public:
~CTheClassWithDestructor()
{
int TheValue_ = 0;
}
private:
int TheValue_;
};
int _tmain(int argc, _TCHAR* argv[])
{
int size;
CTheClass* pArrayTheClass = new CTheClass[1];
size = _msize(pArrayTheClass);
delete [] pArrayTheClass;
CTheClassWithDestructor* pArrayTheClassWithDestructor
= new CTheClassWithDestructor[1];
size = _msize(pArrayTheClassWithDestructor); /// ASSERT On this line
delete [] pArrayTheClassWithDestructor;
return 0;
}
With Visual C++, new calls the malloc function.
This is partially true: the new expressions in your code do call operator new to allocate memory and operator new does indeed call malloc. But the pointer to the initial element that is yielded by the new expression is not necessarily the pointer obtained from malloc.
If you dynamically allocate an array of objects that require destruction (like your CTheClassWith_string type), the compiler needs to keep track of how many elements are in the array so that it can destroy them all when you delete the array.
To keep track of this, the compiler requests a slightly larger block from malloc then stores some bookkeeping information at the beginning of the block. The new expression then yields a pointer to the initial element of the array, which is offset from the beginning of the block allocated by malloc by the bookkeeping information.
In the VST spec, a buffer of multichannel audio data is passed around.....
MyClass::ProcessDoubleReplacing(double **inputs, double **outputs, int frames)
{
//and accessed like this...
outputs[channel][sample] = inputs[channel][sample]
}
I want to create a similar "2d pointer array", but am not having much success. I can create a simple pointer and iterate through it reading/writing values....
double* samples;
samples[0] = aValue;
.... but am having a crash festival trying to implement something that will allow me to...
samples[0][0] = aValue;
What would be the correct way to implement this?
double* samples;
samples[0] = aValue;
That's really bad. :( Please don't do this! "sample" is just a pointer to somewhere in your memory.
The memory it points to is not allocated at all, but you're writing to this memory...
You can allocate a block of memory either from the heap or from the stack. However, the stack has a size limit (configured in your compiler settings) - so for larger blocks (like audio data) you would typically allocate it from the heap. But you have to take care, that you won't leak memory from the heap - the stack memory is automatic managed by the scope of your variable, so that's easier to start with.
In C/C++ you can allocate memory from the stack like this:
double samples[512];
then you can do stuff like:
samples[0] = aValue; // change value of 1st sample in sample buffer with 512 elements
or
double* pointerToSample = samples[255]; // point to 256ths sample in the sample buffer
pointerToSample[127] = aValue; // change value of 384ths sample (256+128) in our sample buffer with 512 elements
and so on...
BUT if you just do,
double* pointerToSample;
pointerToSample[127] = aValue;
You're actualing writing to unallocated memory! Your pointer points somewhere, but there is no allocated memory behind it.
Be carefull with this! Also never access pointerToSample if the samples variable is already out-of-scope: the memory pointerToSample points to is no longer allocated otherwise.
To allocate memory from the heap in C++ there is the keyword new (to allocate memory) and delete (to free memory afterwards) dynamically.
i.e.
double *samples = new double[512];
will allocate a block of memory for your sample data. But after using it, you have to manually delete it - otherwise you're leaking memory. So just do:
delete[] samples;
after you're finished with it.
Last but not least to answer your question how to create a two dimensional array to call the method ProcessDoubleReplacing()
int main(int argc, char ** argv){
/* create 2 dimensional array */
int** samplesIn = new int*[44100];
int** samplesOut = new int*[44100];
for(int i = 0; i < 44100; ++i){ // 1s # 44.1Khz
samplesIn[i] = new int[2]; // stereo
samplesOut[i] = new int[2]; // stereo
}
/* TODO: fill your input buffer with audio samples from somewhere i.e. file */
ProcessDoubleReplacing(samplesIn, samplesOut, 44100);
/* cleanup */
for(int i = 0; i < 44100; ++i) {
delete [] samplesIn[i];
delete [] samplesOut[i];
}
delete [] samplesIn;
delete [] samplesOut;
return 0;
}
#Constantin's answer pretty much nailed it, but I just wanted to add that in your implementation you should not allocate the buffers in your process() callback. Doing so may cause your plugin to take too much time, and as a consequence the system can drop audio buffers, causing playback glitches.
So instead, these buffers should be fields of your main processing class (ie, the AEffect), and you should allocate their size in the constructor. Never use new or delete inside of the process() method or else you are asking for trouble!
Here's a great guide about the do's and don'ts of realtime audio programming.
If you want to write something in C++ to provide a similar interface like the one you showed, I would use std::vector for managing the memory like this:
vector<vector<double>> buffers (2,vector<double>(500));
This only stores the data. For an array of pointers you need an array of pointers. :)
vector<double*> pointers;
pointers.push_back(buffers[0].data());
pointers.push_back(buffers[1].data());
This works since std::vector makes the guarantee that all elements are stored adjacent and linearly in memory. So, you're also allowed to do this:
double** p = pointers.data();
p[0][123] = 17;
p[1][222] = 29;
It's important to note that if you resize some of these vectors, the pointers might get invalid in which case you should go ahead and get the new pointer(s).
Keep in mind that the data member function is a C++11 feature. If you don't want to use it, you can write
&some_vector[0] // instead of some_vector.data()
(unless the vector is empty)
Instead of passing a double** to some function, you might be interested in passing the buffers vector directly by reference, though, this obviously won't work if you want your interface to be C compatible. Just saying.
Edit: A note on why I chose std::vector over new[] and malloc: Because it's the right thing to do in modern C++! The chance of messing up in this case is lower. You won't have any memory leaks since the vector takes care of managing the memory. This is especially important in C++ since you might have exceptions flying around so that functions might be exited early before the use of a delete[] at the end of the function.
I'm having trouble understanding arrays of pointers to structures. I created this simple example to try and understand them better. Although it compiles, I keep getting "BAD ACCESS" crashes (nonsense pointers) at the point shown below. Can anyone explain why this is wrong?
#include <iostream>
using namespace std;
struct complex_num {
double real_part;
double imag_part;
};
void init_complex(complex_num *element) {
element->real_part = -1.0; // <--- EXECUTION STOPS HERE.
element->imag_part = 1.0;
}
int main(int argc, char *argv[]) {
int n = 5;
complex_num *array[n]; // Allocates for an array of n pointers to
// the complex_num structure, correct?
for (int i = 0; i < n; i++) {
init_complex(array[i]);
}
return 0;
}
I know there are better ways to do this. I know this is very C in style. Please don't suggest a different data structure. I'm curious specifically about arrays of pointers to structures. Thanks!
You did not allocate memory for your complex_num objects, only for an array with pointers to it. So when you call init_complex, it operates on a pointer to an invalid location.
Try this:
for (int i = 0; i < n; i++) {
array[i] = new complex_num();
init_complex(array[i]);
}
Your statement complex_num *array[n] creates an array of n pointers to complex_num. Meaning, the array can hold n pointers to complex_num; but the pointers themselves are still uninitialized. They point to random locations - every uninitialized primitive (to which pointers belong as well) in C++ will usually simply contain whatever value was in the memory location before the allocation. This will almost certainly lead to unexpected results, as there is no way (or at least no reasonably easy way) of telling where an uninitialized pointer points to.
So you'd have to make each pointer in the array point to some properly set up memory location containing complex_num; only after that you should access (read or write) the values in the complex_num where the pointer points to. To make it e.g. point to a dynamically allocated, new complex_num object, use the above code (notice the new keyword which does the dynamic allocation).
Side note: "Raw" pointers, pointing to dynamically allocated objects, like shown above, are tricky to handle (you should not forget to call delete after you are finished, otherwise you will leak memory), therefore the recommended practice is usually to use smart pointers (like std::shared_ptr, introduced with C++11).
yes, there is no memory allocated to the pointers you have declared. It doesn't point to any valid structure object
I have this function:
char* ReadBlock(fstream& stream, int size)
{
char* memblock;
memblock = new char[size];
stream.read(memblock, size);
return(memblock);
}
The function is called every time I have to read bytes from a file. I think it allocates new memory every time I use it but how can I free the memory once I have processed the data inside the array? Can I do it from outside the function? Processing data by allocating big blocks gives better performance than allocating and deleting small blocks of data?
Thank you very much for your help!
Dynamic arrays are freed using delete[]:
char* block = ReadBlock(...);
// ... do stuff
delete[] block;
Ideally however you don't use manual memory management here:
std::vector<char> ReadBlock(std::fstream& stream, int size) {
std::vector<char> memblock(size);
stream.read(&memblock[0], size);
return memblock;
}
Just delete[] the return value from this function when you've finished with it. It doesn't matter that you're deleting it from outside. Just don't delete it before you finish using it.
You can call:
char * block = ReadBlock(stream, size);
delete [] block;
But... that's a lot of heap allocation for no gain. Consider taking this approach
char *block = new char[size];
while (...) {
stream.read(block, size);
}
delete [] block;
*Note, if size can be a compile time constant, you can just stack allocate block.
I had a similar question, and produced a simple program to demonstrate why calling delete [] outside a function will still deallocate the memory that was allocated within the function:
#include <iostream>
#include <vector>
using namespace std;
int *allocatememory()
{
int *temppointer = new int[4]{0, 1, 2, 3};
cout << "The location of the pointer temppointer is " << &temppointer << ". Locations pointed to by temppointer:\n";
for (int x = 0; x < 4; x++)
cout << &temppointer[x] << " holds the value " << temppointer[x] << ".\n";
return temppointer;
}
int main()
{
int *mainpointer = allocatememory();
cout << "The location of the pointer mainpointer is " << &mainpointer << ". Locations pointed to by mainpointer:\n";
for (int x = 0; x < 4; x++)
cout << &mainpointer[x] << " holds the value " << mainpointer[x] << ".\n";
delete[] mainpointer;
}
Here was the resulting readout from this program on my terminal:
The location of the pointer temppointer is 0x61fdd0. Locations pointed to by temppointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
The location of the pointer mainpointer is 0x61fe10. Locations pointed to by mainpointer:
0xfb1f20 holds the value 0.
0xfb1f24 holds the value 1.
0xfb1f28 holds the value 2.
0xfb1f2c holds the value 3.
This readout demonstrates that although temppointer (created within the allocatememory function) and mainpointer have different values, they point to memory at the same location. This demonstrates why calling delete[] for mainpointer will also deallocate the memory that temppointer had pointed to, as that memory is in the same location.
Yes. You may call delete from outside of the function. In this case though, may I suggest using an std::string so you don't have to worry about the management yourself?
first thing to note: memory allocated with new and delete is completely global. things are not automatically deleted when pointers go out of scope or a function is exited. as long as you have a pointer to the allocation (such as the pointer being returned there) you can delete it when ever and where ever you want. the trick, is just makeing sure other stuff doesn't delete it with out you knowing.
that is a benefit with the sort of function structure the fstream read function has. it is fairly clear that all that function is going to do is read 'size' number of bytes into the buffer you provide, it doesn't matter whether that buffer has been allocated using new, whether its a static or global buffer, or even a local buffer, or even just a pointer to a local struct. and it is also fairly clear that the function is going to do nothing more with the buffer you pass it once it's read the data to it.
on the other hand, take the structure of your ReadBlock function; if you didn't have the code for that it would be tricky to figure out exactly what it was returning. is it returning a pointer to new'd memory? if so is it expecting you to delete it? will it delete it it's self? if so, when? is it even a new pointer? is it just returning an address to some shared static buffer? if so, when will the buffer become invalid (for example, overwritten by something else)
looking at the code to ReadBlock, it is clear that it is returning a pointer to new'd memory, and is expecting you to delete it when ever you are done with it. that buffer will never be overwritten or become invalid until you delete it.
speed wise, thats the other advantage to fsream.read's 'you sort out the buffer' approach: YOU get the choice on when memory is allocated. if you are going "read data, process, delete buffer, read data process delete buffer, ect.... " it is going to be alot more efficient to just allocate one buffer (to the maximum size you will need, this will be the size of your biggest single read) and just use that for everything, as suggested by Stephen.
How about using a static char* memblock; It will be initialised just once and it wont allocate memblock a new space everytime.
Since c++11, one can use std::unique_ptr for this purpose.
From https://en.cppreference.com/book/intro/smart_pointers :
void my_func()
{
int* valuePtr = new int(15);
int x = 45;
// ...
if (x == 45)
return; // here we have a memory leak, valuePtr is not deleted
// ...
delete valuePtr;
}
But,
#include <memory>
void my_func()
{
std::unique_ptr<int> valuePtr(new int(15));
int x = 45;
// ...
if (x == 45)
return; // no memory leak anymore!
// ...
}