#My attempt on a vector class

27 messages · Page 1 of 1 (latest)

delicate ocean
#

https://github.com/stley/vector

I'm beginning to understand pointers, memory allocation, etc. First implementations used default data types such as int, float and double in conjunction with malloc.
Last commit implemented non-trivial support for classes and struct types (therefore, new and delete operators are used).
There are some methods to be reimplemented tho (such as those that use iterators, something that I couldn't get a hold yet).
Maybe making safer methods (in order to prevent some of the UB that std::vector doesn't prevent)

GitHub

Contribute to stley/vector development by creating an account on GitHub.

molten lava
#

make it constexpr!

cobalt trench
cobalt trench
delicate ocean
molten lava
cobalt trench
#

wait, that only works for transient allocation right ?

#

I think im conflating it with static_vector, which has fixed capacity

vestal wolf
vestal wolf
# delicate ocean Since vector constructor sets both size_ and capacity_ = 0, operation would be b...

I'm not a big fan of these kind of setups, because it forces you to really track how your capacity can change and make sure the "forbidden" value can never come up
usually a vector has some feature that let the user "control" the capacity to some extent, so I went to check and you offer those features as well
if you create a new vector (capacity 0) then resize or reserve to 1, the issue can manifest

https://godbolt.org/z/xM1rcdnzn

berkeley::vector<int> vec;
vec.reserve(1);
vec.push_back(0);
vec.push_back(1);

either you special case "capacity == 1" everywhere, or you should force grow to also work from capacity 1

#

one suggestion amongst a lot of possible options, would be to go for

size_t new_cap = 1 + capacity_ + (capacity_/2);

which doesn't quite have the exact growth factor of 1.5, though close enough, but more interestingly (imo) you either get a bigger value, or you've grown to such immense sizes that you're wrapping around and you should probably fail/throw
so I guess you'd replace the if(!capacity_) new_cap = 2; by if(new_cap <= capacity_) return false; or something

#

or you assume/force these sizes to never happen and kick out the if

#

right, might as well go with

size_t new_cap = std::min(1 + capacity_ + (capacity_/2), max_size());
if (new_cap <= capacity_ && capacity_ < max_size())
  new_cap = max_size();

considering that you do ::operator new( (sizeof(T)*new_cap) ) right after

#

this bit is a tad weird

    T* new_ptr = static_cast<T*>(::operator new( (sizeof(T)*new_cap) ));

    if (!new_ptr) return false;

maybe you're using some specific compiler extensions/options, but the specific version of ::operator new you are using is meant to throw an exception on allocation failure, in standard conforming c++ it can never give you a null pointer

if you want a null pointer on allocation failure, I would recommend to ::operator new( size, std::nothrow ) instead

delicate ocean
#

Hey there, really appreciate the feedback!

delicate ocean
delicate ocean
delicate ocean
vestal wolf
#

it just so happens that the overload you used (maybe unintentionally) throws on failure
skipping some details, the standard explicitly mandates this behaviour for this specific overload, and compilers may take advantage of that no matter what you do

#

;asm -O2

#include <new>

extern void* one_time_emergency_memory;

void* my_allocate(std::size_t to_allocate)
{
  void* allocation = ::operator new(to_allocate);
  if (!allocation)
    return one_time_emergency_memory;
  else
    return allocation;
}
gentle phoenixBOT
#
Assembly Output
my_allocate(unsigned long):
  jmp operator new(unsigned long)

vestal wolf
#

this is a disfunctional function, but it's to illustrate the point, the generated code for my_allocate "just" leaves everything to operator new

#

as in, the compiler completely eliminated the branch where operator new returns nullptr because it cannot legally happen

vestal wolf
vestal wolf
#

I haven't read your whole code, and I kinda need to go, but feel free to ask for clarifications about what I said, I'll check back later