Consider this code:
using namespace std;
int* get()
{
unique_ptr<int> p (new int[4]);
return p.get();
}
int main(int argc, char **argv)
{
int *arr1=get();
int* arr2=get();
for(int i=0;i<4;i++)
{
arr1[i]=i;
arr2[i]=i*2;
}
for(int i=0;i<4;i++)
cout << arr1[i];
return 0;
}
arr1 and arr2 point to the same area of memory.
So they share the same values.
I don't understand why, when I call arr2=get() :
unique_ptr<int> p (new int[4]);
This object shouldn't be created again? It isn't deleted because still reachable by arr1.
How to get two arrays of different memory areas?
I am fairly sure you are playing with undefined behavior which is bad.
the data being pointed to was destroyed when the unique pointer was destroyed, the fact the values are the same, and the same slot was chosen is luck.
for pointers to array type use a vector
std::vector<int> get()
{
return std::vector<int>(4);
}
int main()
{
std::vector<int> arr1=get();
std::vector<int> arr2=get();
return 0;
}
for normal single value pointers then you can return a unique_ptr;
std::unique_ptr<int> get(){
return std::unique_ptr<int>(new int(0));
}
:::
std::unique_ptr<int> ptr=get();
There are a memory leak in such kind of usage of smart pointers. unique_ptr will use operator delete in order to free the allocated memory, but you need delete []. Also the return value of get function will be an invalid ptr because the unique_ptr will free the allocated area. If you need dynamically allocated arrays then use std::vector.
Related
void foo(int i)
{
char* p = new char[10];
if (i)
{
p = 0;
}
delete[] p;
}
In the above code snippet, p resource was referenced to zero. Will this create a memory leak in my code?
Yes it leaks in case i != 0.
Your variable p points to some address in memory and by doing p = 0; you erase that pointer. So the instruction delete[] p; will work for a nullptr pointer and you'll not free the allocated memory.
For this type of problems we use smart pointers (unique_ptr, shared_ptr, ...) and STL containers and objects like std::string, std::vector<char>, std::list<char> and so on.
So, in your case you have to change code to something like that
{
char* p = new char[10];
if (i)
{
if (p) {
delete[] p;
p = 0;
}
}
if (p) {
delete[] p;
p = 0;
}
}
Inside your function foo, you are setting the value of the pointer p, which actually is a pointer to the beginning of your dynamic array, to 0 if i is non-zero:
if(i)
{
p = 0;
}
Therefore, when i is non-zero, p no longer points to the start of your array and the delete command will fail to deallocate the array that you create inside the function.
So yes, when i is non-zero, your function will leak memory. I wouldn't change p if I were you. Keep that unchanged until the end so that you call delete [] on it and deallocate the array.
Alternatively, consider using a std::vector instead:
std::vector<char> vec(10);
This does something equivalent except it will take care of the memory allocation/deallocation for you automatically.
Can someone please tell, what is wrong with this code? The purpose is to find the factors from a given number 'n'.
vector <int> * factor(int *n){
vector<int> * arr;
for(int i=1;i<=*n;i++){
if(*n%i==0){
arr->push_back(i);
}
}
return arr;
}
int main(){
int n,j=0;
vector<int> *arr;
cin>>n;
arr = factor(&n);
for(auto it=arr->begin();it!=arr->end();++it){
cout<<*it;
}
return 0;
}
Your 1st problem is that you pass an address of a local variable to a function that expects to read the content of that address. You haven't allocated memory for that variable so it is a "temporary" variable which is saved on the stack, and not on the heap, so factor cannot access it.
If you feel like unnecessarily allocating memory, you should define n as a pointer, allocate memory with "new" and pass the pointer to factor, like so:
int* n = new int;
arr = factor(n);
However, you could've easily passed factor the local variable as is, so it'll receive a copy of it. That requires you to edit your function and remove the *'s from the n's.
Your second problem is defining arr as a pointer to vector. All it does is create a variable which says : "hey, i can point you in the direction where the real vector object is at!", but there is no such object since you haven't allocated memory for it.
For this code, it is best to work with local variables, nothing here requires memory allocation, so i would suggest the following edit:
vector <int> factor(int n){
vector<int> arr;
for(int i=1;i<=n;i++){
if(n%i==0){
arr.push_back(i);
}
}
return arr;
}
int main(){
int n,j=0;
vector<int> arr;
cin>>n;
arr = factor(n);
for(auto it=arr.begin();it!=arr.end();++it){
cout<<*it;
}
return 0;
}
If I have a C type raw pointer, is it possible to create a std::vector from the same type that owns the pointer's data without any data copy (only moving)? What motivates me for asking this question is the existence of data() member function for std::vector which means vector's elements are residing somewhere in the memory consecutively.
Edit: I have to add that the hope I had was also intensified by the existence of functions like std::make_shared.
I don't think that this is directly possible, although you're not the first one to miss this feature. It is even more painful with std::string which doesn't have a non-const data member. Hopefully, this will change in C++17.
If you are allocating the buffer yourself, there is a solution, though. Just use a std::vector up-front. For example, assume you have the following C-style function,
extern void
fill_in_the_numbers(double * buffer, std::size_t count);
then you can do the following.
std::vector<double>
get_the_numbers_1st(const std::size_t n)
{
auto numbers = std::vector<double> (n);
fill_in_the_numbers(numbers.data(), numbers.size());
return numbers;
}
Alternatively, if you're not so lucky and your C-style function insists in allocating the memory itself,
extern double *
allocate_the_buffer_and_fill_in_the_numbers(std::size_t n);
you could resort to a std::unique_ptr, which is sadly inferior.
std::unique_ptr<double[], void (*)(void *)>
get_the_numbers_2nd(const std::size_t n)
{
return {
allocate_the_buffer_and_fill_in_the_numbers(n),
&std::free
};
}
No, std::vector is not designed to be able to assume/utilize a pre-existing array for its internal storage.
Yes, provided that you've created and populated the vector before getting the pointers and that you will not
erase any element
you will not add new elements when vec.size() == vec.capacity() - 1 ,,, doing so will change the address of the elements
Example
#include <iostream>
void fill_my_vector<std::vector<double>& vec){
for(int i=0; i<300; i++){
vec.push_back(i);
}
}
void do_something(double* d, int size)
{ /* ..... */ }
int main(){
std::vector<double> vec;
fill_my_vector(vec);
//You hereby promise to follow the contract conditions, then you are safe doing this
double* ptr;
int ptr_len = vec.size();
ptr = &vec[0];
//call do_something
do_something(ptr, ptr_len);
//ptr will be alive until this function scope exits
}
EDIT
If you mean managing the data from an already created array, you can't... vector manages its own array... It cannot take ownership of an array that wasn't created by its class (vector).
struct item
{
unsigned int a, b, c;
};
item* items[10];
delete items[5];
items[5] = NULL;
The above code works
But the below method is not working
int * arr1[30];
delete (arr1+5);
I am a beginner, Please tell me why I am able to delete in case of structure pointer but not in case of int
pointer
You're seemingly misunderstanding what delete is for: it's purely and simply to release memory allocated by new, not to 'delete' elements of arrays.
So you might use it like this:
int *p = new int;
//...
delete p;
When you allocate arrays, you must instead use delete[], like this:
int *q = new int[23];
//...
delete [] q;
But at no point should you try and delete something that hasn't been new'ed, or use the non-matching version of delete, e.g. delete [] p; or delete q; above.
If what you really want is some sort of 'array' from which you can remove elements, try this:
#include <vector>
struct item
{
unsigned int a, b, c;
};
int main()
{
std::vector<item> items(10);
items[5].a = 23;
items.erase(items.begin() + 5);
return 0;
}
Are you allocating heap memory anywhere? You are not doing so in the code above. You are lucky that the first delete does not crash.
When using the (arr1+5) approach, you are passing the memory address of the array slot itself at index 5, not the int* that the slot contains. To delete the int* that is contained in the slot at index 5, you have to dereference the pointer value, eg:
delete *(arr1+5);
I am storing pointers to elements of a vec_A in an array A* a_ptrs[3] . Assume that vec_A will not be resized. So, a_ptrs[i] will point to the correct element.
My question is:
Suppose A* a_ptrs[3] is declared in a class B. Since it is not created using 'new' I am guessing I don't need to delete it in the destructor. Am I right??
class A {
public:
int getNumber();
A(int val);
~A(){};
private:
int num;
};
A::A(int val){
num = val;
};
int A::getNumber(){
return num;
};
int main(){
int i =0;
int num;
std::vector<A> vec_A;
for ( i = 0; i < 10; i++){
vec_A.push_back(A(i));
}
A* a_ptrs[3];
a_ptrs[0] = &vec_A[0];
a_ptrs[1] = &vec_A[3];
a_ptrs[2] = &vec_A[5];
for (i = 0; i<3; i++){
std::cout<<"\n: a_ptrs[i].getNumber() = "<<a_ptrs[i]->getNumber();
}
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
Yep, thats correct. You don't need to use delete. The only issue is if the vector is resized e.g. by calling push_back etc - but you called that out in your post.
Yes, delete is used only for variables allocated with new.
Correct, since there is no dynamic memory allocation in the program.
My Suggestion is to use vector.reserve() function to reserve the size of the vector which will improve program performance.
Basically when you add an element to CArray(MFC) or std::vector it reallocates necessary memory and copies the elements so it will lead to memory fragmentation and will degrade program speed.