C++ Tips: Difference between revisions

From FlightGear wiki
Jump to navigation Jump to search
Line 10: Line 10:


* Use <tt>SGGeod</tt> instead of basic longitude/latitude/elevation doubles. It's easier to pass to other methods, type safe (can't confuse order of lat/lon) and unit-safe (degrees vs radians vs meters vs feet is explicit in the API).
* Use <tt>SGGeod</tt> instead of basic longitude/latitude/elevation doubles. It's easier to pass to other methods, type safe (can't confuse order of lat/lon) and unit-safe (degrees vs radians vs meters vs feet is explicit in the API).
* Never pollute the namespace in a header file, via <tt>using</tt> declarations, even for standard library types. I.e don't be lazy and write <tt>using std::string;</tt> in a header - each time you refer to <tt>string</tt>, <tt>vector</tt>, etc, you need to fully qualify the name with <tt>std::</tt>. It's a bit more type, but much safer for code that includes the header file. (In source files, you are welcome to do as you please)


== C++ Efficiency ==
== C++ Efficiency ==

Revision as of 22:02, 7 October 2009

This page collects various tips and common pitfalls when working with the C++ code. Some are generic, others are FlightGear specific

Primitive Types

  • Use the SimGear primitive types for quaternions, vectors and matrices - the PLIB ones are deprecated (and PLIB will be removed at some point in the future). In some places it makes sense to use OSG types directly - that decision is left to the developer to decide which makes more sense.

Standards

  • Use SG_LOG calls instead of <cout> and iostreams.
  • Use SGGeod instead of basic longitude/latitude/elevation doubles. It's easier to pass to other methods, type safe (can't confuse order of lat/lon) and unit-safe (degrees vs radians vs meters vs feet is explicit in the API).
  • Never pollute the namespace in a header file, via using declarations, even for standard library types. I.e don't be lazy and write using std::string; in a header - each time you refer to string, vector, etc, you need to fully qualify the name with std::. It's a bit more type, but much safer for code that includes the header file. (In source files, you are welcome to do as you please)

C++ Efficiency

Rather than duplicate the many fine works in this area, it's likely you should find and read 'Effective-C++', 'More Effective-C++' and 'Effective STL', all by Scott Meyers. The most critical points are repeated here, though.

  • Always pass aggregate types by (const) reference, especially STL containers, string or mathematical tuples such as SGQuat or SGVec3. String copying in particular is common and leads to many wasteful malloc and free calls. Passing STL containers by value is extremely wasteful, as is returning them by value - pass them into methods by a reference, and out the same way. This avoids any container copying at all, hopefully.

Pitfalls

  • Watch out for confusing geocentric coordinates (SGGeoc) and geodetic coordinates (SGGeod). If you use the SG types, the correct conversions are enforced, but many places in the code create a geocentric type from geodetic lat/lon. Geocentric computations are less expensive to compute, but there are very few places where the performance difference will be noticeable.
  • Magnetic vs true headings, bearings and courses - watch out for whether any bearing values are true or magnetic. Most user-facing properties are magnetic, since that's what is used in charts, runway headings, etc. Internal computations (SGGeodesy::direct, etc) work in true bearings, so conversion is required. The magvar code computes magnetic variation for you, but also note the variation depends on position - if you read the variation from the property tree, you're getting the value at the user's latitude / longitude.
  • When the simulation is paused, SGSubsystem::update is still called, but with dt = 0. This can easily lead to divide-by-zero errors in code; check for it explicitly if working on subsystem code that is doing time-dependency calculations.