By the way, I use subinstr to make my code play different instruments for different groups of notes on the midi keyboard and to make easy changes to the groups. For example, I have something like:
instr 1040, 1041, 1042, 1043, 1044, 1045
iFreq = p4
iAmp = p5
iNumKey = notnum() - 20
if (iNumKey < 1 || iNumKey > 88) goto skipnote
instr = 1000 + iNumKey
aOut subinstr instr, iFreq, iAmp
aOut = aOut * madsr(0.01, 0, 1, 5)
outs aOut, aOut
As you can see, Instr 1 "subinstr" to the right instrument, based on the key number of the note (for the sake of simplicity I omitted the code for groups other than 40-45).
In this simple schema, if I want to make the keys 46 and 47 play from the instr 1040, all I have to do is to add ", 1046, 1047" to the right of the "instr 1040..." statement. Similarly, if I want to isolate the keys 42 and 43 and make them play from a separated instrument, all I have to do is to remove 1042 and 1043 from the "instr 1040..." statement and create a new instrument for the extracted key numbers:
instr 1042, 1043
I don't know if I can do this with UDOs in such an easy and elegant way, and I suspect that subinstr could be much more efficient (for example, being that actually in Csound the passage of parameters to the UDOs is done "by value", each time you call an UDO with a-rate input/output params it's like to copy an array of "ksmps" double floats for each a-type parameter... From my experiments, this could slow down very much the performance, and it's for this reason that as long as Csound will not allow passing parameters by reference I will always be reluctant to use UDOs to process a-rate signals in real-time).