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

Both sides previous revision Previous revision
Next revision
Previous revision
eliminate_char_arrays [2017/09/01 15:40]
shane [Application in the VanillaJuce code]
eliminate_char_arrays [2017/09/01 16:09] (current)
shane [Eliminating unnecessary String() constructor invocations]
Line 33: Line 33:
  
 ===== Use of "const char*" for string literals ===== ===== 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>
 +
  
  
eliminate_char_arrays.1504280449.txt.gz ยท Last modified: 2017/09/01 15:40 by shane