GetDunne Wiki

Notes from the desk of Shane Dunne, software development consultant

User Tools

Site Tools


eliminate_char_arrays

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
eliminate_char_arrays [2017/09/01 15:39]
shane created
eliminate_char_arrays [2017/09/01 16:09] (current)
shane [Eliminating unnecessary String() constructor invocations]
Line 30: Line 30:
 }; };
 </code> </code>
-The resulting code changes elsewhere, to eliminate clumsy uses of things like ''sprintf()'' and //juce::String::copyToUTF8()'', etc. are too obvious (and embarrassing) to even list here.+The resulting code changes elsewhere, to eliminate clumsy uses of things like ''sprintf()'' and //juce::String::copyToUTF8()//, etc. are too obvious (and embarrassing) to even list here. 
 + 
 +===== Use of "const char*" for string literals ===== 
 +I do still use the ''char'' type in a very specific way in **VanillaJuce**, to declare a static array of string literals in ''SynthWaveform.cpp'': 
 +<code cpp> 
 +const char* const SynthWaveform::wfNames[] = { 
 +    "Sine", "Triangle", "Square", "Sawtooth" 
 +}; 
 +</code> 
 +As Jules pointed out in his list of code issues, it's acceptable and preferable to use string literals (which the C++ compiler will interpret as being of type ''const char*'') to initialize //juce::String// variables, and in place of //juce::String//-typed function parameters. This is because //juce::String// has been defined to include a constructor which takes a ''const char*'' argument, and therefore, the C++ compiler will silently invoke this constructor function to turn the given literal string into a //juce::String// instance automatically. In terms of the above table of waveform names, I could have made it an array of //juce::String// objects, but this would be redundant. 
 + 
 +Ordinarily, I get uneasy whenever the C++ compiler silently inserts function calls in this way, because it obscures the flow of control. In this case I'm OK with it, because it is a well-established JUCE programming convention. 
 + 
 +===== Eliminating unnecessary String() constructor invocations ===== 
 +A perfect example of why it's a good idea to avoid writing ''String("xyz")'' and just use the literal ''"xyz"'' arose in some code I used in //SynthParameters::getXml()//, which is a series of function calls like this: 
 +<code cpp> 
 +xml->setAttribute(String("masterLevel"), masterLevel); 
 +</code> 
 +I had used the ''String("xyz")'' construct simply because I didn't know much about JUCE's XML functions, and had copy-pasted the code from an example I found elsewhere. When I looked, though, I noticed that the //juce::XmlElement::setAttribute()// function is actually declared as 
 +<code cpp> 
 +void XmlElement::setAttribute (const Identifier& attributeName, const double number) 
 +</code> 
 +along with many related definitions, for different data-types in the second argument. In every case, however, the first argument is not a //juce::String// at all, but something called a //juce::Identifier//. Presumably, the C++ compiler is accepting my //juce::String// arguments by silently invoking an appropriate //juce::Identifier// constructor I wasn't even aware of. Depending how good its optimization is, this might be quite inefficient. The lesson is clear: whenever possible, use simple string literals, and trust that the JUCE library has defined appropriate constructors to perform whatever conversions may be necessary. All the ''setAttribute'' calls in my //SynthParameters::getXml()// implementation now look like this: 
 +<code cpp> 
 +xml->setAttribute("masterLevel", masterLevel); 
 +</code>
  
-===== Use of const char* for string literals ===== 
  
  
eliminate_char_arrays.1504280354.txt.gz · Last modified: 2017/09/01 15:39 by shane