C++ is love
-
- ditch the
using namespace std;
in header files, 2) you don't have virtual destructor for `MemoryPool` and 3) if you're using C++17 you might want to checkmemory_resource
class/header
- forgive me for asking, but why? edit: whoops that was an error. if anything it was supposed to be inside the file's namespace 2) MemoryPool is an interface - a pure abstract base. what is the purpose of a virtual destructor in such a contract as it holds no resources? - never mind. I was thinking about the call chain backwards. derived classes need to have their destructor called if the base goes out of scope. i forgot. I'm rusty. 3) I'm targeting C++11 for now because reasons having to do with the platforms this is primarily for.
Real programmers use butterflies
- ditch the
-
- forgive me for asking, but why? edit: whoops that was an error. if anything it was supposed to be inside the file's namespace 2) MemoryPool is an interface - a pure abstract base. what is the purpose of a virtual destructor in such a contract as it holds no resources? - never mind. I was thinking about the call chain backwards. derived classes need to have their destructor called if the base goes out of scope. i forgot. I'm rusty. 3) I'm targeting C++11 for now because reasons having to do with the platforms this is primarily for.
Real programmers use butterflies
- you don't want to introduce bunch of names from
std
into client's scope, can cause all kind of nasty problems for users. C++ name lookup is complex as it is. 2) if I got a pointer toMemoryPool
and tried to delete the referenced object, I would invoke undefined behavior, even thought virtual methods are strongly suggesting me that I should be able to do it Some more points, since you said C++ is love: 4)virtual void* alloc(const size_t size)=0;
-const
is needless 5)if(!TCapacity)
will give you a warning (on /W4 maybe) ifTCapacity
is 0, but 6) the bigger problem is `uint8_t m_heap[TCapacity]`, since zero-sized arrays is not standard C++ So I would either go withstatic_assert
and ensure that 0 is not valid value or make specialization for that cas.
-
- forgive me for asking, but why? edit: whoops that was an error. if anything it was supposed to be inside the file's namespace 2) MemoryPool is an interface - a pure abstract base. what is the purpose of a virtual destructor in such a contract as it holds no resources? - never mind. I was thinking about the call chain backwards. derived classes need to have their destructor called if the base goes out of scope. i forgot. I'm rusty. 3) I'm targeting C++11 for now because reasons having to do with the platforms this is primarily for.
Real programmers use butterflies
And some more: 7) You invoke undefined behavior in `~DynamicMemoryPool` by calling
delete
operator instead ofdelete[]
8) i guesscapacity
,used
,next
should beconst
-qualified C++ IS LOVE :) -
Not much improvement, just a few observations: 1. Identifiers starting with underscores are reserved. If you use them then your program is non-conforming for no good reason. 2. The comparison against capacity in both the static and dynamic classes result in never being able to use the last byte of the pool: The "used()>=capacity" should be "used()>capacity". To test it instantiate a pool of 10 bytes and allocate 6. The (capacity() - used()) is then 4, but a further allocation of 4 fails. A further allocation of 3, on the other hand, succeeds and (capacity() - used()) is then 1. 3. The static pool could benefit from a #warning directive when C is too large. Right now a 8MB C when instantiating it (1024 * 1024 * 8) would almost certainly overflow the stack, and 8MB is not a lot of memory.
- gotta love C++, since rules for reserved names are even more complex that, depending on scope, case, number of underscores... 3) or
static_assert
to keep it in the family language.
- gotta love C++, since rules for reserved names are even more complex that, depending on scope, case, number of underscores... 3) or
-
- you don't want to introduce bunch of names from
std
into client's scope, can cause all kind of nasty problems for users. C++ name lookup is complex as it is. 2) if I got a pointer toMemoryPool
and tried to delete the referenced object, I would invoke undefined behavior, even thought virtual methods are strongly suggesting me that I should be able to do it Some more points, since you said C++ is love: 4)virtual void* alloc(const size_t size)=0;
-const
is needless 5)if(!TCapacity)
will give you a warning (on /W4 maybe) ifTCapacity
is 0, but 6) the bigger problem is `uint8_t m_heap[TCapacity]`, since zero-sized arrays is not standard C++ So I would either go withstatic_assert
and ensure that 0 is not valid value or make specialization for that cas.
1&2 - see my edited post 4, i use const descriptively, even if it doesn't do anything, unless there's a reason I shouldn't 5, yeah that's a nasty habit of mine 6 I introduced a static_assert to fix that in my later code.
Real programmers use butterflies
- you don't want to introduce bunch of names from
-
And some more: 7) You invoke undefined behavior in `~DynamicMemoryPool` by calling
delete
operator instead ofdelete[]
8) i guesscapacity
,used
,next
should beconst
-qualified C++ IS LOVE :)whoops, and yeah your probably right. i love const and i hate const because i always forget it.
Real programmers use butterflies
-
whoops, and yeah your probably right. i love const and i hate const because i always forget it.
Real programmers use butterflies
- you want to disable copy and move operations (constructor and assign operation) on
StaticMemoryPool
and copy operations onDynamicMemoryPool
10)~StaticMemoryPool() {}
don't provide user-defined special members functions if they are not really necessary and if you do have to define them because language rules deleted them, use= default
to retain possible triviality of these operations General rule is if you need to provide a single user-defined SMF, you need to provide them all. It was called rule-of-three, now it's known as rule-of-five. Think about using clang-format and clang-tidy (they integrate well with VS these days).
- you want to disable copy and move operations (constructor and assign operation) on
-
- you want to disable copy and move operations (constructor and assign operation) on
StaticMemoryPool
and copy operations onDynamicMemoryPool
10)~StaticMemoryPool() {}
don't provide user-defined special members functions if they are not really necessary and if you do have to define them because language rules deleted them, use= default
to retain possible triviality of these operations General rule is if you need to provide a single user-defined SMF, you need to provide them all. It was called rule-of-three, now it's known as rule-of-five. Think about using clang-format and clang-tidy (they integrate well with VS these days).
Okay I am aware of the rule of five but I don't actually want copy and move operations to work, consequently, no move and copy operations. Currently if I try to do those things, I'm pretty sure it doesn't compile. What's wrong with that?
Real programmers use butterflies
- you want to disable copy and move operations (constructor and assign operation) on
-
Okay I am aware of the rule of five but I don't actually want copy and move operations to work, consequently, no move and copy operations. Currently if I try to do those things, I'm pretty sure it doesn't compile. What's wrong with that?
Real programmers use butterflies
Are you sure it does not compile? [Copy and move operations does not produce error](https://godbolt.org/z/8vadqM) Rules for which SMFs get deleted by compiler and which remain defaulted are a bit complex, so that's why it's better to be explicit about it and
= delete
those that you don't want and= default
those that you want to keep. The second point is to always prefer= default
over{}
since you retain triviality which is actual concept. Trivial type are easier to handle, subject to more optimizations and can be used in wider range of situations. It something that you probably don't need for arena allocator, so in this case it would be about habit and consistency. -
Are you sure it does not compile? [Copy and move operations does not produce error](https://godbolt.org/z/8vadqM) Rules for which SMFs get deleted by compiler and which remain defaulted are a bit complex, so that's why it's better to be explicit about it and
= delete
those that you don't want and= default
those that you want to keep. The second point is to always prefer= default
over{}
since you retain triviality which is actual concept. Trivial type are easier to handle, subject to more optimizations and can be used in wider range of situations. It something that you probably don't need for arena allocator, so in this case it would be about habit and consistency.Now that you mention it I'm not sure. I guess I should be explicit.
Real programmers use butterflies
-
1&2 - see my edited post 4, i use const descriptively, even if it doesn't do anything, unless there's a reason I shouldn't 5, yeah that's a nasty habit of mine 6 I introduced a static_assert to fix that in my later code.
Real programmers use butterflies
honey the codewitch wrote:
4, i use const descriptively, even if it doesn't do anything, unless there's a reason I shouldn't
To whom this description is directed? Users of the interface don't not care about it. Implementer of the interface is [free to leave it out when override the function](https://godbolt.org/z/as7Mzv), since compiler ignores
const
when doing overload resolution. It is just implementation thing leaking into syntax of function signature, but not really affecting it. You can keep it class implementing abstract function to prevent changes to the parameter in the function's body, but in the base class it just confusing. -
declaring it on the stack? ouch. I only return char*s from functions if I'm using some kind of memory management scheme that allows for it. Unless you implement one C and C++ ... doesn't. I can't judge people too badly though, considering I just got schooled on using leading underscores in my local member names (a habit I picked up from C#) But still, you should understand scoping if you're going to get paid to code in the thing.
Real programmers use butterflies
Yes, in C#, we (used to) use underscores for local member names. In C++, we used 'm_' for member names. The 'm' told us that it was a class (or struct) member.
-
Yes, in C#, we (used to) use underscores for local member names. In C++, we used 'm_' for member names. The 'm' told us that it was a class (or struct) member.
i should have known. i went back to that style and I absolutely hate it.
Real programmers use butterflies