RS-MET icon indicating copy to clipboard operation
RS-MET copied to clipboard

Can you rewrite your entire library so you don't use new/delete?

Open elanhickler opened this issue 8 years ago • 26 comments

https://lefticus.gitbooks.io/cpp-best-practices/content/04-Considering_Safety.html

😸

Edit: Or at least begin to stop using that paradigm.

Edit: Also, never use macros. Don't do it for your constants! Lorcan sent me that link, I'm reading through all of it now.

elanhickler avatar Nov 04 '17 16:11 elanhickler

yeah...there are a lot of good points in these articles. i think, the constant macros can easily be replaced by actual constant numbers.

i'm not so sure about abolishing new/delete, though (and replacing it by smart-pointers - that's what it would mean, right?). the main argument seems to be that you could forget to call delete - well, juce has a nice mechanism to detect such memory leaks and smart-pointers may create some data and performance overhead compared to simple raw pointers (and the syntax is quite ugly as well , imho)

RobinSchmidt avatar Nov 13 '17 09:11 RobinSchmidt

also, raw pointers are sometimes more flexible because you can explicitly control the lifetime of objects, for example the deletion order

RobinSchmidt avatar Nov 13 '17 09:11 RobinSchmidt

That's fair... but sometimes I don't even see the need for pointers. shrug I'll have to find specific examples.

elanhickler avatar Nov 13 '17 14:11 elanhickler

I don't even see the need for pointers

wut? i use them all over the place. for example a slider keeps a pointer to its underlying parameter, a MetaControlledParameter a pointer to its MetaManager, a MetaParameter a list of pointers to its dependent parameters, the ModulationManager to a list of ModulationSources, Targets and Connections, the SnoothingManager to its smoothers, etc... ALL OVER THE PLACE!!!

edit: ok, you said "sometimes". i missed that

RobinSchmidt avatar Nov 13 '17 15:11 RobinSchmidt

using std::vector instead of c-style arrays is a very good idea because you can view the content of the array in the debugger. also: avoid using juce::Array for the same reason

RobinSchmidt avatar Nov 13 '17 18:11 RobinSchmidt

you can see contents of juce::Array with natvis... still trying to figure out how to use it, I'll give you the details when I figure it out. Jim knows. Edit: It's a native VS feature, and I think XCode also has something.

elanhickler avatar Nov 13 '17 20:11 elanhickler

hey robin, I tried to avoid using "new" by NOT using any kind of pointer, but then the issue was that the constructor required certain things. By removing requirements on construction, would that alleviate the use of "new"? Maybe I can post specific examples of where you could remove a few construction requirements.

elanhickler avatar Dec 29 '17 04:12 elanhickler

hmmm...yeah - i actually also would prefer to use direct member variables instead of pointers that are assigned via "new" in the constructor (and use the dot "." instead of "->"). ...however - when you need to pass things to the constructor call - like, for example, a mutex-lock object for thread safety, it's sometimes not so easily possible to do it with without pointers. ...but actually, much of the use of pointers is a remnant of using an older version of juce which required using pointers.

yes, maybe give specific examples - maybe, i can think of alternatives then. for example, if you have a direct variable and a constructor requires a pointer to an object, you can sometimes use the address operator "&". we do that sometimes with the smoothing-manager, for example; the plugin has a direct member and passes a pointer to the module(s) via &

it's hard to change the whole framework at once to a different strategy of doing things, but maybe it can be done one by one, incrementally

RobinSchmidt avatar Dec 29 '17 06:12 RobinSchmidt

jura_AudioModule.h image

elanhickler avatar Dec 29 '17 07:12 elanhickler

hmm...ok - but what is the use case? i mean in which circumstance do you need to call that constructor without having a valid AudioModule object around which you can pass? do you want to create an empty editor, i.e. an editor that edits nothing?

RobinSchmidt avatar Dec 29 '17 07:12 RobinSchmidt

...hmm...ok...i explicitly consider that case in the comment for the 2nd constructor. .... but it's sooo long ago. why do we need empty editors? :-O

RobinSchmidt avatar Dec 29 '17 07:12 RobinSchmidt

i don't have a use case other than cleaner code.

...I need to figure out how to instantiate arbitrary number of child modules, going to look at #131

elanhickler avatar Dec 29 '17 07:12 elanhickler

do you still have to call callback when callback is assigned? I need to not do that as there will be some nullptrs (trying to remove annoying constructor requirements)

i think, the reason we call the callback initially when it gets assigned was to ensure consistency between the parameter value and the corresponding dsp-core-object value. i introduced that after some discussion with you, i guess i could check against nullptr on assignment and when it is a nullptr indeed, not call it...and/or add a bool parameter to the function call whether or not to call the callback

edit: i think, we are on the wrong thread....however..

let me just manually do "call all callbacks" somewhere to solve that consistency problem, or solve it elsewhere. is there a convenience function for that?

well, wouldn't loading a default preset solve that as well?

elanhickler avatar Dec 29 '17 08:12 elanhickler

well i tried loading a default preset, that doesn't help since not all parameters are edited when loading a patch.

strange issue came up as I was trying to move toward "creating child modules at runtime"

createWidgets is called twice:

image

which means I "push back" BasicEnvelopeModules twice, so I get double the envelope modules... wtf?

image

elanhickler avatar Dec 29 '17 09:12 elanhickler

createWidgets is called twice

yeah - actually the constructor of the editor is called twice somewhere in the juce code. ...happens generally with all plugins - i need to figure out why.. ...am i doing something wrong anywhere? this is a big wtf for me as well.

edit: it happens only with the plugins, not with standalone versions. strange.

RobinSchmidt avatar Dec 30 '17 14:12 RobinSchmidt

just wondering: why are you creating audio-modules in the editor at all?

RobinSchmidt avatar Dec 30 '17 14:12 RobinSchmidt

ROBIN! Don't ask my questions like that!

Obviously it's because I don't know what I'm doing! So tell me the correct way! 😞

Edit: Actually, it's more that I'm trying to consolidate the process of creating a module. I don't know how you would go about creating a module during runtime, so I figured the first step is to consolidate the process/code.

elanhickler avatar Dec 30 '17 16:12 elanhickler

well, ok - if you create modules at runtime then obviously some kind of editor must trigger the creation of the module. nothing wrong with that. what is the "e" variable here? i suppose a pointer to the underlying AudioModule? that would make sense. ...but if that's happening in the constructor of the editor (we are looking at createWidgets here right?) then it's actually at startup time (of the editor) - and in this case it seems a bit odd to me. if you create child-modules at initialization time, i think, the right place to do that is in the constructor of the parent module (or some function that is called from there)

RobinSchmidt avatar Dec 30 '17 17:12 RobinSchmidt

soo...the oddness is actually not so much in creating AudioModules in the editor - but in creating AudioModules in the constructor of the editor

RobinSchmidt avatar Dec 30 '17 17:12 RobinSchmidt

should I do it in createFilterPlugin?

elanhickler avatar Dec 30 '17 17:12 elanhickler

If I'm going to be creating modules during runtime, I want it to all be the same process, I don't want to have modules being created in constructor AND have another way of doing it during run time.

elanhickler avatar Dec 30 '17 17:12 elanhickler

in this case, maybe what you want is a factory function? that is just some function that creates an object (typically via "new"), possibly calls some setup functions to initialize it and returns the pointer to it (handing over ownership to the caller), something like:

AudioModule* myAudioModuleCreator()
{
  AudioModule* m = new MyModuleClass;
  m->setOldYear(2017);
  m->setNewYear(2018);
  m->setHappy(true);
  // ...etc....
  return m;
}

you can get more fancy by creating a factory object (that may have a state) and implement the factory function(s) as member function(s).

RobinSchmidt avatar Dec 30 '17 20:12 RobinSchmidt

maybe look at my class AudioModuleFactory in the ToolChain.h/cpp file

RobinSchmidt avatar Dec 30 '17 20:12 RobinSchmidt

I don't want new!!!!!!!!!! Why can't I just "push a new object into a vector"?

edit: oh, because of locks...

elanhickler avatar Dec 30 '17 21:12 elanhickler

how - if not via new - would you create the object?

RobinSchmidt avatar Dec 30 '17 21:12 RobinSchmidt

just push to a vector and then send the contents of the vector via pointers for whatever... the only thing possibly stopping it would be the constructor needs.

elanhickler avatar Dec 30 '17 21:12 elanhickler