I want to create a std::vector<float> vpd which will be a reference to float*.
float * old = new float[6];
for (int i = 0; i < 6; i++)
{
old[i] = i;
}
vector<float> vpd(6);
auto refasd = &*vpd.begin();
*refasd = *old;
vpd[0] = 23;
cout << old[0] << endl;
How should I modify the code, if I want get 23 from cout?
You can't. std::vector is not designed to take ownership of a raw pointer.
Maybe you can make do with std::unique_ptr<float[]>, but the better solution is to directly use std::vector.
As alternative, you might use std::span (C++20)
float* old = new float[6];
std::iota(old, old + 6, 0);
std::span<float> vpd(old, 6);
vpd[0] = 23;
std::cout << old[0] << std::endl;
delete[] old;
You could also create a vector of std::reference_wrapper objects that refer to the original float array - may that be std::vector<float> or a newed float*. An example:
vector<std::reference_wrapper<float>> vpd(old, old + 6); // ¹
vpd[0].get() = 23.f;
cout << old[0] << endl; // prints 23
¹) Thanks to #StoryTeller for pointing out that vpd can be directly initialized.
As std::vector has its own memory structure you cannot map vector<float> or even vector<float*> to an array of float. However you can map each vector item to an array one.
float* old = new float[6];
for (int i = 0; i < 6; i++)
{
old[i] = i;
}
vector<float*> vpd(6);
int i = 0;
for (auto it = vpd.begin(); it != vpd.end(); it++)
{
*it = &old[i++];
}
*vpd[0] = 23;
*vpd[2] = 45;
cout << old[0] << endl << old[2] << endl;
Output
23
45
Depending on version of C++ you'll have some options (if I understand the problem):
if you have an older c++ version then c++11 I would in this case declear std::vector as:
// then you really need to make sure u delete the memory as well
std::vector<float*> vpd(6);
If however you got c++11 or higher I would use either std::share_ptr or std::unique_ptr depending on if you would like to share the memory space or not. Either this will ensure the memory is deleted by it self without having to do a "delete float*;" which is nice.
You can read about std::shared_ptr at: https://en.cppreference.com/w/cpp/memory/shared_ptr and std::unique_ptr at: https://en.cppreference.com/w/cpp/memory/unique_ptr
// For unique_ptr
std::vector<std::unique_ptr<float>> vpd(6);
// for std::shared_ptr
std::vector<std::shared_ptr<float>> vpd(6);
I would say that if you can then use unique_ptr rather then shared_ptr due to shared_ptr has som extra komplexitity within to be make sure the memory not used before deleteing memory space.
Related
I am trying to do a project that involves overloading new and delete. I am storing an array of void pointers (pointers to random memory that is allocated) in a double void pointer. Of course, this array will need to be resized to account for further void pointers that come in.
This is the intialization of the array, allocArraySize(int) is set to 4.
void** allocArray = (void**) calloc ( allocArraySize, sizeof(void*) );
Setting all values to nullptr..
for(int i=0; i<allocArraySize; i++){ *(allocArray + i*sizeof(void*)) = nullptr; }
However, when trying to resize the array, I noticed that my original array of void pointers is modified when I create a new temporary array(temp) to store them in.
// PRINTS THE ORIGINAL ARRAY
for(int i=0; i<allocArraySize; i++){std::cout<<i<<" = "<<*( allocArray + i*sizeof(void*))<<"\n";}
void** tempArray = (void**)calloc(allocArraySize, sizeof(void*));
// PRINTS THE ORIGINAL ARRAY
for(int i=0; i<allocArraySize; i++){std::cout<<i<<" = "<<*( allocArray + i*sizeof(void*))<<"\n";}`
Notice, I am not even putting the array values in the temp array yet and I am still getting this problem. Why is that? why is this random value being assigned to this spot when it is indeed initialized? How is this one new temp array variable messing with my array?
NOTE: This is basically the complete code. Only thing missing is a main function, iostream, and the declaration for allocArraySize. Yes, WELL aware that I am not freeing these poor double pointers. I just wanted to create the problem in simplest terms possible.
The sizeof multiplier shouldn't be there:
*(allocArray + i*sizeof(void*))
// ^^^^^^^^^^^^^^ this shouldn't be here
void** is strongly typed. It participates in proper offset calculation via pointer arithmetic. There is no need here for sizeof offset calculations. That loop, which appears to be crafted to dump the pointer values in the sequence, should therefore be:
for(int i=0; i<allocArraySize; i++)
{
std::cout<< i << " = " << allocArray[i] << "\n";
}
You are indexing the pointers incorrectly i * sizeof(void*) rather than i.
for(int i=0; i<allocArraySize; i++){ allocArray[i] = nullptr; }
Firstly, you rather shouldn't use calloc in C++ code. Especially if you program uses both new expression and calloc\malloc, it may lead to to UB due to mismatching deletors.
allocArraySize got type void** , so it's pointer to pointer. Result of expression *allocArraySize got same sizeof as void* or uintptr_t type. Arithmetic with pointers automatically increment pointer by amount required to point at next object of same type.
C++ way to write it doesn't even require such arcane knowledge either, all you should do is to use a new expression and list-initialize it with empty list to get same effect as calloc does in C.
void** allocArray = ::new void*[allocArraySize] {};
for(int i = 0; i < allocArraySize; ++i)
{
std::cout<< i << " = " << allocArray[i] << "\n";
}
When using new/delete from within of overloaded one, it's essential to use :: or it would lead to infinite recursion.
allocArray[i] is an equivalent of *(allocArray + i)
Overloading new\delete aside. But truly C++ way to do that is to avoid naked pointers and use containers if possible. New\delete might be wrappers around usage of some memory pool class.
// do we really need a vector of pointers?
auto allocArray = std::vector<void*>(allocArraySize, nullptr);
int i = 0;
for( auto &v : allocArray )
std::cout<< (i++) << " = " << v << "\n";
In C++20 range-based for loop becomes more contained thanks to init-statement
for(int i = 0; auto &v : allocArray )
std::cout<< (i++) << " = " << v << "\n";
It's possible to declare a fixed-size array of raw pointers on the stack, which can be used to dynamically allocate memory (objects) at runtime. I'm trying to replace raw pointers with smart pointers, but this pattern is failing.
The following code summarizes the problem, hope it's not too verbose:
#include <iostream>
#include <vector>
#include <memory>
const int SIZE = 10;
//older method of declaring an array of std::vector<int> pointers with
//memory leak risks, using automatic (stack-based) allocation for the
//array of pointers, dynamic (heap-based) allocation for the vectors:
std::vector<int>* arr[SIZE];
for (int i = 0; i < SIZE; i++) {
arr[i] = new std::vector<int>;
}
for (int i = 0; i < SIZE; i++) {
arr[0]->push_back(i);
}
for (int val : *arr[0]) {
std::cout << val << " "; //prints 0 - 9 as expected
}
That works as usual, but when trying to implement smart pointers I can only get a smart pointer to an array of std::vector to work, i.e.:
//declaring smart pointer to an array of std::vector<int>, which is not
//automatic (stack-based) allocation of the array
std::unique_ptr<std::vector<int>[]> arr2 (new std::vector<int>[SIZE]());
for (int i = 0; i < SIZE; i++) {
arr2[0].push_back(i);
}
for (int val : arr2[0]) {
std::cout << val << " "; //prints 0 - 9 as expected
}
As far as I can tell, this is not something smart pointers support? :
//attempting to declare an array of smart pointers to std::vector<int>
std::unique_ptr<std::vector<int>> arr3[SIZE];
for (int i = 0; i < SIZE; i++) {
std::cout << &arr3[i] << std::endl; //prints memory locations
if (arr3[i]->empty()) { //seg faults # runtime
std::cout << "empty vector\n";
}
arr3[i] = new std::vector<int>; //won't compile
}
(Please let me know if there are basic problems with this pattern as well)
In the last code block, it looks like arr3 is getting memory assigned but I cannot figure out how to use it to create a new std::vector.
//older method of declaring an array of std::vector<int> pointers with
//memory leak risks, using automatic (stack-based) allocation for the
//array of pointers, dynamic (heap-based) allocation for the vectors:
Automatic storage duration arrays don't leak. Their elements can, however. For example, when they are pointers that point to dynamically allocated elements. Smart pointers are there to replace raw pointers, so do just that - replace T* with, for example, std::unique_ptr<T>. Do not replace an array of automatic storage duration with a smart pointer - at most use std::array. I believe you are looking for something like this:
std::unique_ptr<std::vector<int>> arr3[SIZE];
// or better - std::array<std::unique_ptr<std::vector<int>>, SIZE> arr3{};
for (int i = 0; i < SIZE; i++) {
arr3[i] = std::make_unique<std::vector<int>>(); // notice the syntax...
// ... and the fact that you first allocate the vector, *then* use the ->empty()
std::cout << &arr3[i] << std::endl;
if (arr3[i]->empty()) {
std::cout << "empty vector\n";
}
}
I am learning c++ pointers. I wrote some code to see if I understood correctly.
It might look a little weird. I made it a little complex on purpouse. Could you please tell me If I understood correctly? Or if there is something wrong that I didn't understand?
#include <iostream>
using namespace std;
int main()
{
int **x = new int*[20];
*x = new int [5]; //x[0] ==>[0,0,0,0,0]
*(x+1) = new int [3]; //x[1] ==>[0,0,0]
*x[0] = 10; //x[0][0] = 10
*(x+1)[0] = 20; //x[1][0] = 20
cout << x[0][0] << endl;
cout << x[1][0] << endl;
delete [] *x;
delete [] *(x+1);
delete [] x;
return 0;
}
Due to operator precedence, the lines
*x[0] = 10;
*(x+1)[0] = 20;
are equivalent to
*(x[0]) = 10;
*((x+1)[0]) = 20;
I am not sure whether you meant that. IMO, it will be better to use:
(*x)[0] = 10;
(*(x+1))[0] = 20;
As best as I'm able to determine, your code is correct with respect to what your comments expect is happening, prevents memory leaks, and is free of Undefined Behavior, which is all fine and good.
But consider, for a second, how much unnecessary boilerplate code you had to write to make this work. And then consider the following code using std::unique_ptr, which is exactly identical to your code in terms of behavior, but removes the boilerplate that is responsible for deleting the memory, by using a class which handles that behavior automatically:
#include<memory>
int main()
{
auto x = std::make_unique<std::unique_ptr<int[]>[]>(20);
x[0] = std::make_unique<int[]>(5); //x[0] ==>[0,0,0,0,0]
x[1] = std::make_unique<int[]>(3); //x[1] ==>[0,0,0]
*x[0] = 10; //x[0][0] = 10
//This will no longer compile because, while technically correct, this kind of pointer arithmetic
//is inherently unsafe and prone to mistakes
//*(x+1)[0] = 20; //x[1][0] = 20
x[1][0] = 20;
cout << x[0][0] << endl;
cout << x[1][0] << endl;
//No more deletes needed; `std::unique_ptr` manages its own memory and deletes when needed
return 0;
}
Now consider the next code, which simplifies further by using a more robust idiom for dynamically-sized arrays, std::vector:
#include<vector>
int main()
{
std::vector<std::vector<int>> x(20);
x[0].resize(5); //x[0] ==>[0,0,0,0,0]
x[1].resize(3); //x[1] ==>[0,0,0]
x[0][0] = 10;
x[1][0] = 20;
cout << x[0][0] << endl;
cout << x[1][0] << endl;
return 0;
}
This is a pretty clear case-study in why, for most purposes, you should prefer things like std::unique_ptr<T[]> or std::vector<T> for describing "Arrays of T". And for 2d arrays, std::unique_ptr<std::unique_ptr<T[]>[]> or std::vector<std::vector<T>>, which describe the same semantics as your original code.
The only incorrect thing is, new int[] does not initialize its memberes. After *x=new int[5], x can be {123,456,789,-123,-456} or anything else.
struct Struct_t {
int Value1;
int Value2;
};
vector<Struct_t> Struct;
Struct.resize(10, Struct_t());
for (int i = 0; i < 10; ++i)
{
Struct[i].Value1 = (i + 10) * 3;
Struct[i].Value2 = (i + 5) * 2;
}
How can I create a pointer to Struct[i]?
What I want to do essentially is something like this, but I'm sure this can be done better:
int value = 6;
Struct_t temp = Struct[value], *s;
s = &temp;
s->Value1 = 42;
s->Value2 = 6;
Main goal is, that I can easily create a pointer to Struct[n] with 1 line/function.
So far, the provided answers are missing the elephant in the room. You could create a pointer to a vector element like so:
(Fault-prone) Code Listing
#include <iostream>
#include <vector>
struct Struct_t {
int Value1;
int Value2;
};
int main(void)
{
std::vector<Struct_t> sVec;
sVec.resize(10, Struct_t());
int count = 0;
for (std::vector<Struct_t>::iterator vIt = sVec.begin(); vIt != sVec.end(); ++vIt)
{
vIt->Value1 = (count + 10) * 3;
vIt->Value2 = (count + 5) * 2;
count++;
}
Struct_t* pStruct = &sVec[5];
std::cout << "sVec[5] = (" << pStruct->Value1 << "," << pStruct->Value2
<< ")" << std::endl;
return 0;
}
Sample Output
sVec[5] = (45,20)
However, vector is not an abstract type you want to use if you will be generating pointers to individual elements of the vector/"array". When the vector needs to be re-sized (shrink or grow), the iterators are invalidated, so your pointers will point to now-freed memory, crashing your program. If you want to have raw pointers directly to vector elements, you want to first:
Use a list rather than a vector.
Possibly use managed pointers to handle reference counts.
Finally, when dealing with template classes like vector, list, hash_table, etc, you should try to get used to using the iterator example I used above, as you don't have to worry about checking for exceptions when using an invalid index (the overloaded [] operators can throw exceptions, unless you replace them with the .at() member function instead for element access).
For a std::vector, &v[i], gives you a pointer to the i'th element. Your sample code becomes:
int value = 6;
Struct_t* s = &Struct[value];
s->Value1 = 42;
s->Value2 = 6;
So the one-liner is Struct_t* s = &Struct[value];
There is nothing wrong with doing this, but like most aspects of C++, you need to understand what you are doing. The above code is perfectly valid and guaranteed by the standard. (Also note that the code in this answer avoids an error in the original code where s was a pointer to a temporary copy and no changes were made to the contents of the Struct vector.)
Yes, resizing Struct will invalidate any pointers made before the resize, and yes, using iterators is often a better technique. But this is a correct and reasonable answer to the original question.
I have the following matrix:
int N = 3;
complex<double>* complexvector = new complex<double>[N];
for(int i=0; i<N; i++)
{
complexvector[i]=complex<double>(i+1,i+1);
}
complex<double>** complexMatrix = new complex<double>*[N];
for(int i=0; i<N; i++)
{
complexMatrix[i] = new complex<double>[N];// allocate an array to each pointer
}
complexMatrix[0][0] = complex<double>(1,1);
complexMatrix[0][1] = complex<double>(2,2);
complexMatrix[0][2] = complex<double>(3,3);
complexMatrix[1][0] = complex<double>(4,4);
complexMatrix[1][1] = complex<double>(5,5);
complexMatrix[1][2] = complex<double>(6,6);
complexMatrix[2][0] = complex<double>(7,7);
complexMatrix[2][1] = complex<double>(8,8);
complexMatrix[2][2] = complex<double>(9,9);
complex<double>* returnvector = new complex<double>[N];
returnvector = preformcholesky(complexMatrix, complexvector, N);
And I do the Cholesky here:
complex<double>* preformcholesky(complex<double>** matrix, complex<double>* vector,
int size)
{
std::cout << "start cholesky" << std::endl;
Map<MatrixXcd, RowMajor> mat(*matrix,size,size);
Map<VectorXcd> vec(vector,size);
printMatrix(matrix,size);
std::cout << "mat" << mat << std::endl;
std::cout << "vec" << vec << std::endl;
//mat.llt();
VectorXcd x = mat.llt().solve(vec);
std::cout << "coeff" << x << std::endl;
return x.data();
}
The trouble is when printing out "mat", it goes like this:
mat (1,1) (0,3.21143e-322) (6,6)
(2,2) (4,4) (0,3.21143e-322)
(3,3) (5,5) (7,7)
Where do those (0,3.21143e-322) come from? If I print "matrix" then that is OK, so I think that the map has gone wrong. If you need some more code then just let me know. I am new to Eigen so maybe some basic mistake. I am using C++ and Linux.
There are several things wrong with that code. The return value of performcholesky, for example, is a pointer to a local variable that does not exist anymore after performcholesky has returned, and you overwrite a pointer to allocated memory with this dangling pointer, leaking that memory. Why don't you work with Eigen::MatrixXcd directly? You'd save yourself a world of pain debugging all that later.
Anyway, the problem you ran into this time is that the Eigen::Map constructor expects a flat array, not a pointer to pointer. It is to be used like this:
// It would also work with naked new, but naked new leads to pain, fear, anger,
// and suffering. Also to long hours of debugging.
std::vector<std::complex<double> > data(N * N);
for(int i = 0; i < N * N; ++i) {
data[i] = std::complex<double>(i, i);
}
Eigen::Map<Eigen::MatrixXcd, Eigen::RowMajor> mat(&data[0], N, N);
An interesting question is why the two arrays that you did not pass to the constructor nevertheless show up in the map, if somewhat shifted. The answer is: By pure happenstance, new gave you three slabs of memory that were right behind each other on the heap. This also explains the strange artifacts you see in the map; those are bookkeeping data of your heap implementation for the corresponding allocated blocks, reinterpreted as doubles. In essence, the memory around complexmatrix[0] looks like this:
the area that Eigen::Map uses
+-----------------------------------------------------------------+
|(1,1)|(2,2)|(3,3)|bookkeeping|(4,4)|(5,5)|(6,6)|bookkeeping|(7,7)|(8,8)|(9,9)|
+-----------------+ +-----------------+ +-----------------+
^-complexmatrix[0] ^-complexmatrix[1] ^-complexmatrix[2]
Naturally, this is not behavior you can depend upon. The code could just as well show any random data or crash with a segfault if the blocks new gives you are arranged in a different manner.