4

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?

DeiDei
  • 10,205
  • 6
  • 55
  • 80
Artur Domasik
  • 41
  • 1
  • 3
  • Are you maybe looking for this: https://stackoverflow.com/questions/2434196/how-to-initialize-stdvector-from-c-style-array – uceumern Nov 21 '18 at 10:52
  • Is it about telling the vector to use your "preallocated" buffer instead of the one a vector manages internally, or is it just that you want to refer to to the vector's internal buffer in terms of a `float*`-type? – Stephan Lechner Nov 21 '18 at 10:52
  • maybe you meant `vpd[0] = 23; *old = *refasd;` ? – M.M Nov 21 '18 at 10:52

5 Answers5

5

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.

Quentin
  • 62,093
  • 7
  • 131
  • 191
5

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;
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
Jarod42
  • 203,559
  • 14
  • 181
  • 302
4

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.

lubgr
  • 37,368
  • 3
  • 66
  • 117
2

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
serge
  • 992
  • 5
  • 8
  • You ruined your cache locality by doing this, though – Lightness Races in Orbit Nov 21 '18 at 11:17
  • @LightnessRacesinOrbit cold you please explain in more details? – serge Nov 21 '18 at 11:58
  • @LightnessRacesinOrbit the link is cool in design context however I still don't see the relation with reusing of some memory piece accessed by pointers. – serge Nov 21 '18 at 13:25
  • The entire article is about how indirection in your containers reduces performance by thwarting your CPU's cache. Pointers in contiguous containers should be avoided unless necessary for some goal. A contiguous set of data means the cache will function properly when you obtain the first element; that is, the second and third and maybe more will already be ready for reading. If you are extracting pointers and have to dereference each one, the odds of that information being in cache each time are low (unless the "real" data is nearby) so you will have lots of cache misses. This is expensive. – Lightness Races in Orbit Nov 21 '18 at 13:29
  • @LightnessRacesinOrbit Did I understand correctly: the `vector` is more expensive that `vector` with move semantic of `MyClass`? Does `vec.puch_back(new MyClass())` is worse that `vec.push_back(std::move(myClassVar))`? – serge Nov 21 '18 at 13:52
  • 1
    Now you're talking about the cost of _creating_ those elements, not the cost of accessing them. But the answer is still yes. – Lightness Races in Orbit Nov 21 '18 at 13:52
  • I mean the cost of accessing after creating the objects in both cases. – serge Nov 21 '18 at 13:55
  • Very interesting point, I think it will be fine if you present a small test that can show the difference. For example, two vectors with 1M of objects. I will try to test it, too. – serge Nov 21 '18 at 13:59
  • This has been well documented elsewhere. – Lightness Races in Orbit Nov 21 '18 at 15:07
  • @LightnessRacesinOrbit very good point, thank you. [My tests confirm](https://www.arbinada.com/en/node/1648), too. – serge Nov 22 '18 at 13:37
  • @LightnessRacesinOrbit I added [a little test](https://www.arbinada.com/en/node/1648) on `std::reverse` and the pointer list is much faster. Seems that move semantics is not always performant comparing "old school". – serge Mar 11 '19 at 16:51
  • Sorry I don't get it - I don't believe I suggested moving anything – Lightness Races in Orbit Mar 11 '19 at 18:41
  • @LightnessRacesinOrbit sorry, nothing personal, the point is only to see is my test correct. I seem that majority of algorithms using item reallocation (reverse, sort etc.) will be slower with move semantics than with pointers. – serge Mar 12 '19 at 09:21
  • Okay yeah that may be true but for me it's more about the performance of _using_ the resulting container. Depends on your use case ofc! – Lightness Races in Orbit Mar 12 '19 at 10:51
0

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.

Mikael
  • 11
  • 2