Achtergrond: De term "syntactische suiker" werd voorgesteld door Peter Landin in de jaren 60. In C++ zijn vanaf het begin wrapperconstructies ingebouwd, die het schrijven en begrijpen van code vereenvoudigen zonder nieuwe mogelijkheden toe te voegen vergeleken met wat meer gedetailleerde basis syntaxis kan uitdrukken.
Probleem: De hoofd taak van syntactische suiker is het maken van de code korter, expressiever en leesbaarder, het verminderen van de kans op fouten en het versnellen van de ontwikkeling. Aan de andere kant kan overmatige complexiteit van de syntaxis leiden tot verwarring en verborgen problemen in prestaties of begrip van de code.
Oplossing: In C++ omvat syntactische suiker een groot aantal constructies die in wezen wrappers zijn rond meer basiselementen van de taal. Voorbeelden zijn: operator overloads, range-based for, initialisatie lijsten, auto, en lambda-expressies.
Voorbeeldcode:
std::vector<int> v = {1, 2, 3, 4}; for (auto x : v) { std::cout << x << std::endl; } // Equivalent (zonder suiker): for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it) { std::cout << *it << std::endl; }
Belangrijkste punten:
Vervangt auto type-detectie tijdens de compilatie, en is er overhead bij het gebruik ervan?
Nee, auto wordt volledig afgeleid tijdens de compilatie, zonder snelheid verlies, mits correct gebruikt. Fouten ontstaan alleen als auto niet het type is dat men verwacht.
Is for (auto x : v) altijd de snelste manier om een container te doorlopen?
Nee, deze syntaxis kan elementen kopiëren (als & niet is opgegeven), wat zorgt voor prestatieverlies bij grote objecten. Om dit te voorkomen, is het aan te raden om een referentie te gebruiken:
for (auto& x : v) { ... }
Maakt operator overload altijd de code begrijpelijker?
Nee! Operator overload kan ook schadelijk zijn — als operatoren onduidelijk worden overloaded (bijvoorbeeld, overload operator+ zodat deze elementen verwijdert), wordt de code verwarrender.
Gebruik van auto zonder rekening te houden met het returntype van de iteratorfunctie:
std::vector<std::pair<int, int>> data; for (auto x : data) { x.first = 0; } // Wijziging zal niet plaatsvinden, omdat het een kopie is
Voordelen:
Nadelen:
for (auto& x : data) { x.first = 0; } // Wijziging is nu effectief
Voordelen:
Nadelen: