Why uniform initialization (initialization with braces) is recommended? - c++

I see a lot of different places that uniform initialization is recommended. Herb Sutter recommends it, and gives a list when not to use it. It seems that the general consensus is to use this syntax.
However, I don't see why. It has the problem of std::initializer_list takes precedence. Adding a std::initializer_list to a class can break code. With templates, it is not recommended to use. It seems to have more exceptions than the "old" way. None of these problems existed with the old way.
I fail to see why uniform initialization is superior. My conclusion is to keep using () syntax, and use {} only in the case of when I want to call a constructor with std::initializer_list.
Why? What does uniform initialization give?
forbids narrowing: good feature. But, as I have narrowing warnings turn on for all my code (because I want to know all narrowings in my code, not just at initializations), I don't need this feature too much.
most vexing parse: yeah, that's a problem, but I hit this very-very rarely. So it is not a reason (for me) to switch. This places, I may use {}.
is there anything else (maybe, I'm still learning new features of C++)?
With the "old" way, there were no rules to remember, no possible break-of-code. Just use it, and sometimes, very-very rarely, you hit the most vexing parse. That's all.
Is my thinking wrong somewhere?

It seems like you have a decent hold on the technical aspects and nwp raised the other concern I would mention, clarity, in the comments. So I think you have the information you need to make a decision.
That said, I think it's worth doubling-down and trying to highlight the importance of the clarity aspect. In my experience, code clarity is probably the single most importance thing to maintain in a code base. Particularly in terms of avoiding confusion and limiting time wasted on stupid bugs. I think we've all had the experience of spending far too long tweaking the flow of a piece of buggy code only to eventually discover that the issue was a typo or misunderstanding of the original intent.
And to be fair, it sounds like you've tried to address this by sticking to a style and tools that help address that. The standard argument, as nwp started, is that many people aren't okay with deviating from the naming conventions built into the language, nor with using IDEs. I personally sympathize with that logic but also understand why many disregard it as old-fashioned or even a non-issue (particularly for the case of IDEs).
When it comes to matters of clarity, though, I find it hard not to keep in mind that people are annoyingly good at ignoring minor details, even when they might help them. So the more context clues that can hint at where an issue might be the better. Syntax highlighting is great, but I wouldn't bet an evening of debugging on being able to notice something being yellow instead of orange. Yellow and using camel-case? Maybe. Yellow and using braces? Maybe.
Especially when you start getting into code written by someone else, or a long time ago, the more all these little hints start to matter.
At the end of the day, I think that's why people like it enough to recommend it. It's the kind of thing that might just stick out to you when it matters.
Also, a side note in response to your comment about narrowing. Enabling warnings for narrowing may allow you to ignore this benefit for now but in many cases people either 1) can't enable such warnings due to legacy code or 2) don't want to enable such warnings because they intentionally rely on such behavior in certain circumstances and would consider the warnings a nuisance. However, adopting list initialization in either case could help with not only preventing potential issues but also making clear the intent of a given line of code.
To get to the point, people all have different circumstances and preferences. Features like this increase of ways people can improve their code quality/readability while still working within whatever constraints they may have (self-imposed or otherwise).

Related

Is it really better to have an unnecessary function call instead of using else?

So I had a discussion with a colleague today. He strongly suggested me to change a code from
if(condition){
function->setValue(true)
}
else{
function->setValue(false)
}
to
function->setValue(false)
if(condition){
function->setValue(true)
}
in order to avoid the 'else'. I disagreed, because - while it might improve readability to some degree - in the case of the if-condition being true, we have 1 absolutely unnecessary function call.
What do you guys think?
Meh.
To do this to just to avoid the else is silly (at least there should be a deeper rationale). There's no extra branching cost to it typically, especially after the optimizer goes through it.
Code compactness can sometimes be a desirable aesthetic, especially if a lot of time is spent skimming and searching through code than reading it line-by-line. There can be legit reasons to favor terser code sometimes, but it's always cons and pros. But even code compactness should not be about cramming logic into fewer lines of code so much as just straightforward logic.
Correctness here might be easier to achieve with one or the other. The point was made in a comment that you might not know the side effects associated with calling setValue(false), though I would suggest that's kind of moot. Functions should have minimal side effects, they should all be documented at the interface/usage level if they aren't totally obvious, and if we don't know exactly what they are, we should be spending more time looking up their documentation prior to calling them (and their side effects should not be changing once firm dependencies are established to them).
Given that, it may sometimes be easier to achieve correctness and maintain it with a solution that starts out initializing states to some default value, and using a form of code that opts in to overwrite it in specific branches of code. From that standpoint, what your colleague suggested may be valid as a way to avoid tripping over that code in the future. Then again, for a simple if/else pair of branches, it's hardly a big deal.
Don't worry about the cost of the extra most-likely-constant-time function call either way in this kind of knee-deep micro-level implementation case, especially with no super tight performance-critical loop around this code (and even then, still prefer to worry about that at least a little bit in hindsight after profiling).
I think there are far better things to think about than this kind of coding style, like testing procedure. Reliable code tends to need less revisiting, and has the freedom to be written in a wider variety of ways without causing disputes. Testing is what establishes reliability. The biggest disputes about coding style tend to follow teams where there's more toe-stepping and more debugging of the same bodies of code over and over and over from disparate people due to lack of reliability, modularity, excessive coupling, etc. It's a symptom of a problem but not necessarily the root cause.

Why exactly not treat all warnings as errors when there're no warnings in third party code?

This question is not specific to C++, just uses C++ stuff as examples.
A widespread opinion is that "treat all warnings as errors" (like /WX Visual C++ option) is good because a warning is a bug waiting to happen (btw the linked thread is full of "I target for zero warnings" statements).
The only counterargument I've seen so far is that some third-party code will not compile without warnings.
Okay, let's for the duration of this question pretend the compiler has means of temporarily disabling warnings in some code (like this thing in Visual C++):
#pragma warning(push)
#pragma warning(disable:X)
#include <ThirdParty.h>
#pragma warning(pop)
and then the third party code is not a problem anymore.
Assuming we fully control all the code (no third party or we can disable warnings in third party code only) what are reasons for not treating warnings as errors?
Because sometimes you know better than the compiler.
It's not necessarily often with modern compilers, but there are times when you need to do something slightly outside of the spec or be a little tricky with types, and it is safe in this particular case, but not correct. That'll cause a warning, because technically it's usually mostly wrong some of the time and the compiler is paid to tell you when you might be wrong.
It seems to come down to the compiler usually knowing best but not always seeing the whole picture or knowing quite what you mean. There are just times when a warning is not an error, and shouldn't be treated as one.
As you stray further from standard use, say hooking functions and rewriting code in memory, the inaccurate warnings become more common. Editing import tables or module structure is likely to involve some pointer arithmetic that might look a little funny, and so you get a warning.
Another likely case is when you're using a nonstandard feature that the compiler gives a warning about. For example, in MSVC10, this:
enum TypedEnum : int32_t
{
...
};
will give a non-standard extension warning. Completely valid code when you're coding to your compiler, but still triggers a warning (under level 4, I believe). A lot of features now in C++11 that were previously implemented as compiler-specific features will follow this (totally safe, totally valid, still a warning).
Another safe case that gives a warning is forcing a value to bool, like:
bool FlagSet(FlagType flags) { return (flags & desired); }
This gives a performance warning. If you know you want that, and it doesn't cause a performance hit, the warning is useless but still exists.
Now, this one is sketchy as you can easily code around it, but that brings up another point: there may be times when there are two different methods of doing something that have the same results, speed and reliability, but one is less readable and the other is less correct. You may choose the cleaner code over the correct code and cause a warning.
There are other cases where there is a potential problem that may occur, which the warning addresses. For example, MSVC C4683's description literally says "exercise caution when..." This is a warning in the classic sense of the word, something bad could happen. If you know what you're doing, it doesn't apply.
Most of these have some kind of alternate code style or compiler hint to disable the warning, but the ones that don't may need it turned off.
Personally, I've found that turning up the warnings and then fixing them helps get rid of most little bugs (typos, off-by-one, that sort of thing). However, there are spots where the compiler doesn't like something that must be done one particular way, and that's where the warning is wrong.
I've seen 3 reasons:
legacy code: it's a huge undertaking to take code that is riddled with warning and slowly update it so that it's conforming. As any modification, there is a risk of introducing new bugs. Sometimes the potential benefit is not worth the risk.
ignorance: more often than not, it's not really an informed decision, many people don't fiddle with the compiler settings
laziness: aka, sweep under the rug, hopefully only adopted on hobby projects (I am optimistic, I am optimistic, I am optimistic...)
The legacy code is of course a concern, but it can be dealt with efficiently:
treat the legacy code as 3rd party code (aka Great Wall of China)
reform the code, either one file at a time (using a "UglyWarningDeactivator.h" for non-reformed ones) or one warning at a time (by selectively enabling them)
The Great Wall strategy is best used when the tests are as bad as the code or time is scarce. Otherwise, when resources and test confidence allow, I obviously urge you to take an incremental rewrite approach.
On a fresh codebase ? No reason at all. In the worst case, if you really need something tricky (type puning, ...) you can always selectively deactivate the warning for the area of code concerned. And what's really great is that it documents that something fishy is going on!
I disagree with the assertions "no reason at all".
I personally think the correct approach is a zero-warnings policy, but without treating warnings as errors. My assertion is that this increases programmer productivity and responsibility.
I have done both approaches within teams: 1) warnings as errors, and 2) zero-warnings as policy, but not enforced by the compiler. In both cases releases were made without warnings, and the warning levels were kept around zero. In the latter case however, there were occasionally states where the warning level crept up to a handful for a brief period of time.
This led to higher quality code, and a better team. To see how I'll try to come up with a reasonable example from memory. If you're sufficiently clever and motivated you'll be able to poke holes in, but try to stretch your memory and imagination and I think you'll f see my point, regardless of any flaws in my example.
Let's say you have some legacy, c-style code that has been using signed-ints for indexing, and using negative cases for some kind of special handling. You want to modernize the code to take advantage of std algorithms, and maybe something offered by boost. You fix one corner of the code and it's a great proof of concept so you want to add it to the code-review stack because you're pretty sure you want to do the whole thing that way.
Eventually the signed stuff will disappear, but at the moment you're getting warnings that your comparing signed and unsigned ints. If your company is enforcing warning free builds, you could:
To static_casting.
Introduce some unnecessary temporary code.
Go big bang -- migrate the whole thing at once.
This same thing can occur for a large number of reasons. All of these are inferior to pushing a few warnings, discussing the warnings in your team meeting, and cleaning them up at some point in the next few weeks. Casts and temporary code linger and pollute the code for years to come, whereas tracked warnings in a motivated team will get cleaned up quickly.
At this point some people will claim "yeah but people won't be motivated enough" or "not my team, they are all crap" or so on (at least I've frequently heard these arguments). I find this is usually an example of the Fundamental attribution error. If you treat your colleagues like they are irresponsible, uncaring sots, they will tend to behave that way.
While there is a large body of social science to back this up, I can only offer my personal experiences, which are of course anecdotal. I have worked in two teams where we began with a large legacy code base and crapload of warnings (thousands). This is a terrible situation to be sure. In addition to the thousands of warnings, many more were ignored since this would pollute the compiler output too much.
Team 1 : warnings as warnings, but not tolerated
In team 1, we tracked the # of warning in jenkins, and in our weakly team meetings we talked about the number of warnings were doing. It was a 5 man team, of which two of us really cared. When one of us would reduce the warning level, the other would sing their praises in the meeting. When cleaning up a warning removed an undiscovered bug, we advertised the fact. After a few months of this 2 of the other 5 coders joined in and we quickly (within a year) had the warnings down to zero. From time to time the warnings creeped up, sometimes in the tens or twenties. When that happened the developer responsible would come in and say sorry, and explain why they were there and when they expected to get them cleaned up. The one guy who never really got motivated was at least sufficiently motivated by the peer pressure not to add any warnings.
This led to a much improved team atmosphere. In some cases we had productive discussions about what was the best way to deal with a particular warning or class of warnings, which led to us all being better programmers, and the code improving. We all got in the habit of caring about cleaner code, which made other discussions -- like whether or not a 1000 line recursive function with ten parameters was good coding or not -- much easier.
Team 2: Warnings as errors
Team 2 was virtually identical to team 1 at the beggining. Same big legacy code full of warnings. Same number of developers, motivated and unmotivated. In team 2 though one of us (me) wanted to leave warnings as warning, but concentrate on reducing the warnings. My other motivated colleague made the claim that all the other developers were a**holes, and if we didn't make warnings errors they would never get rid of them, and what possible benefit could you get from not doing it? I explained my experience in team 1, but he wasn't having any of it.
I still work in team one. It's a year later and our code is warning free, but it's full of quick hacks to get rid of warnings and unnecessary code. While we have eliminated a lot of real problems, many potential problems have been swept under the rug.
Further, the team cohesion didn't improve a bit. If anything it's degraded, and management is contemplating breaking up the team for that reason. The colleagues who never cared about warnings still don't, and peoples concern for quality hasn't increased. In fact the opposite has occurred. Whenever anyone talks about code quality, that set of people rolls their eyes and thinks of it as another oppressive, silly management obsession that only decreases productivity and has little benefit.
Even worse, whenever we want to introduce another warning that would provide useful information, it's a major project since we would either have to change our warnings-as-errors policy, or fix all the existing warnings before introducing the warning. Because we didn't get practice watching and fixing warnings through intrinsic motivation, the former would likely cause real problems, so instead we add the task to out backlog, and it lingers and lingers.
Another example, which led me to discover this question and write this answer, is C++11's [[deprecated]] feature, which I'd like to use to mark deprecated code so we can gradually phase it out as part of our warnings cleanup. That however is incompatible with all-warnings-as-errors.
My advice: Treat warnings as errors psychologically within your team, but don't tell your compiler to do so. Perhaps treat some particularly pernicious warnings as errors, but be discriminating.
I'd hugely prefer working with a codebase that compiles with a few warnings than one where warning-generating code has been allowed to proliferate due to certain 'not negotiable' warnings being turned off (and I won't pretend this wouldn't happen). At least in the former case the areas that might need some code review are clearly visible just by rebuilding.
Also, having the three categories of Fatal / Warning / Benign allows for a lot of scope to add tiny bits of useful information to the Warning category (see C4061) without it breaking builds. With only a fatal-or-not distinction the list of warnings would have to be a lot more judicious.
In many cases, it's possible for changes in one assembly, or changes in a language, to cause code which used to compile cleanly to start issuing warnings. In some cases, tolerating such warnings temporarily may be better than requiring that all of the edits necessary to eliminate them be performed before anything can be tested.

Which programming technique helps you most to avoid or resolve bugs before they come into production

I don't mean external tools. I think of architectural patterns, language constructs, habits. I am mostly interested in C++
Automated Unit Testing .
There's an oft-unappreciated technique that I like to call The QA Team that can do wonders for weeding out bugs before they reach production.
It's been my experience (and is often quoted in textbooks) that programmers don't make the best testers, despite what they may think, because they tend to test to behaviour they already know to be true from their coding. On top of that, they're often not very good at putting themelves in the shoes of the end user (if it's that kind of app), and so are likely to neglect UI formatting/alignment/usability issues.
Yes, unit testing is immensely important and I'm sure others can give you better tips than I on that, but don't neglect your system/integration testing. :)
..and hey, it's a language independent technique!
Code Review, Unit Testing, and Continuous Integration may all help.
I find the following rather handy.
1) ASSERTs.
2) A debug logger that can output to the debug spew, console or file.
3) Memory tracking tools.
4) Unit testing.
5) Smart pointers.
Im sure there are tonnes of others but I can't think of them off the top of my head :)
RAII to avoid resource leakage errors.
Strive for simplicity and conciseness.
Never leave cases where your code behavior is undefined.
Look for opportunities to leverage the type system and have the compiler check as much as possible at compile time. Templates and code generation are your friends as long as you keep your common sense.
Minimize the number of singletons and global variables.
Use RAII !
Use assertions !
Automatic testing of some nominal and all corner cases.
Avoid last minute changes like the plague.
I use thinking.
Reducing variables scope to as narrow as possible. Less variables in outer scope - less chances to plant and hide an error.
I found that, the more is done and checked at compile time, the less can possibly go wrong at run-time. So I try to leverage techniques that allow stricter checking at compile-time. That's one of the reason I went into template-meta programming. If you do something wrong, it doesn't compile and thus never leaves your desk (and thus never arrives at the customer's).
I find many problems before i start testing at all using
asserts
Testing it with actual, realistic data from the start. And testing is necessary not only while writing the code, but it should start early in the design phase. Find out what your worst use cases will be like, and make sure your design can handle it. If your design feels good and elegant even against these use cases, it might actually be good.
Automated tests are great for making sure the code you write is correct. However, before you get to writing code, you have to make sure you're building the right things.
Learning functional programming helps somehow.
HERE
Learn you a haskell for great good.
Model-View-Controller, and in general anything with contracts and interfaces that can be unit-tested automatically.
I agree with many of the other answers here.
Specific to C++, the use of 'const' and avoiding raw pointers (in favor of references and smart pointers) when possible has helped me find errors at compile time.
Also, having a "no warnings" policy helps find errors.
Requirements.
From my experience, having full and complete requirements is the number one step in creating bug-free software. You can't write complete and correct software if you don't know what it's supposed to do. You can't write proper tests for software if you don't know what it's supposed to do; you'll miss a fair amount of stuff you should test. Also, the simple process of writing the requirements helps you to flesh them out. You find so many issues and problems before you ever write the first line of code.
I find peer progamming tends to help avoid a lot of the silly mistakes, and al ot of the time generates discussions which uncover flaws. Plus with someone free to think about the why you are doing something, it tends to make everything cleaner.
Code reviews; I've personally found lots of bugs in my colleagues' code and they have found bugs in mine.
Code reviews, early and often, will help you to both understand each others' code (which helps for maintenance), and spot bugs.
The sooner you spot a bug the easier it is to fix. So do them as soon as you can.
Of course pair programming takes this to an extreme.
Using an IDE like IntelliJ that inspects my code as I write it and flags dodgy code as I write it.
Unit Testing followed by Continious Integration.
Book suggestions: "Code Complete" and "Release it" are two must-read books on this topic.
In addition to the already mentioned things I believe that some features introduced with C++0x will help avoiding certain bugs. Features like strongly-typed enums, for-in loops and deleteing standard functions of objects come to mind.
In general strong typing is the way to go imho
Coding style consistency across a project.
Not just spaces vs. tab issues, but the way that code is used. There is always more than one way to do things. When the same thing gets done differently in different places, it makes catching common errors more difficult.
It's already been mentioned here, but I'll say it again because I believe this cannot be said enough:
Unnecessary complexity is the arch nemesis of good engineering.
Keep it simple. If things start looking complicated, stop and ask yourself why and what you can do to break the problem down into smaller, simpler chunks.
Hire someone that test/validate your software.
We have a guy that use our software before any of our customer. He finds bugs that our automated tests processes do not find, because he thinks as a customer not as a software developper. This guy also gives support to our customers, because he knows very well the software from the customer point of view. INVALUABLE.
all kinds of 'trace'.
Something not mentioned yet - when there's even semi-complex logic going on, name your variables and functions as accurately as you can (but not too long). This will make incongruencies in their interactions with each other, and with what they're supposed to be doing stand out better. The 'meaning', or language-parsing part of your brain will have more to grab on to. I find that with vaguely named things, your brain sort of glosses over what's really there and sees what is /supposed to/ be happening rather than what actually is.
Also, make code clean, it helps to keep your brain from getting fuzzy.
Test-driven development combined with pair programming seems to work quite well on keeping some bugs down. Getting the tests created early helps work out some of the design as well as giving some confidence should someone else have to work with the code.
Creating a string representation of class state, and printing those out to console.
Note that in some cases single line-string won't be enough, you will have to code small printing loop, that would create multi-line representation of class state.
Once you have "visualized" your program in such a way you can start to search errors in it. When you know which variable contained wrong value in the end, it's easy to place asserts everywhere where this variable is assigned or modified. This way you can pin point the exact place of error, and fix it without using the step-by-step debugging (which is rather slow way to find bugs imo).
Just yesterday found a really nasty bug without debugging a single line:
vector<string> vec;
vec.push_back("test1");
vec.push_back(vec[0]); // second element is not "test1" after this, it's empty string
I just kept placing assert-statements and restarting the program, until multi-line representation of program's state was correct.

C++ interview - testing potential candidates

I have to interview some C++ candidates over the next few weeks and as the most senior programmer in the company I'm expected to try and figure out whether these people know what they are doing.
So has anybody got any suggestions?
Personally I hate being left in a room to fill out some C++ questions so I'd rather do a more complex test that I can chat with the interviewee about their approaches and so forth as we go along. ie it doesn't matter whether they get the right answers or not its how they approach the problem that interests me. I don't care whether they understand obscure features of the language but I do care that they have a good solid understanding of pointers as well as understanding the under lying differences between pointers and references. I would also love to see how they approach optimisation of a given problem because solid fast code is a must, in my opinion.
So any suggestions along these lines would be greatly appreciated!
I wouldn't make them write code. Instead, I'd give them a couple of code snippets to review.
For example, the first would be about design by contract: See if they know what preconditions, postconditions and invariants are. Do a couple of small mistakes, such as never initializing an integer field but asserting that it is >= 0 in the invariant, and see if they spot them.
The second would be to give them bool contains(char * inString, char c). Implement it with a trivial loop. Then ask whether there are any mistakes. Of course, your code here does not check for null in the input parameter inString (even if the very previous question talked about preconditions!). Also, the loop finishes at character 0. Of course, the candidate should spot the possible problems and insist on using std::string instead of this char * crap. It's important because if they do complain, you'll know that they won't add their own char *'s to new code.
An alternative which addresses containers: give them a std::vector<int> and code which searches for prime numbers or counts the odd numbers or something. Make some small mistake. See if they find any issues and they understand the code. Ask in which situation a std::set would be better (when you are going to search elements quite systematically and original order of entrance doesn't matter.).
Discuss everything live, letting them think a couple minutes. Capture the essence of what they say. Don't focus on "coverage" (how many things they spot) because some people may be stressed. Listen to what they actually say, and see if it makes any sense.
I disagree with writing code in interviews. I'd never ask anyone to write code. I know my handwritten code would probably suck in a situation like that. Actually, I have seldom been asked to do so, but when I have, I haven't been hired.
This one is a great complex task, even though it is looking quite harmless.
I believe that a C++ programmer needs more than just generic programming skills, because...
In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg.
Writing bug-free, maintainable C++ code places a much higher demand on a few areas than most languages.
One thing I'll call "pedanticness". You know how some people can spot spelling errors in something at a glance? A C++ programmer needs to be able to spot simple bugs while they read or write code (whether the code is their own or not). A programmer who relies on the "compile and test" technique just to get rid of simple bugs is incompatible with the C++ language, because those bugs don't always lead to immediate failure in C++.
C++ programmers also need a good knowledge of low-level stuff. Pointers, memory allocators, blocking, deadlocks. And "nitty gritty" C++ issues, like multiple inheritance and method hiding and such, particularly if they need to maintain other people's code.
Finally, C++ programmers need to be able to write code that's easy for other people to use. Can they design stuff well?
A good test for the first two areas is "Here's some C++ code I got off the internet. Find the bugs, and identify the unneccessary bits." (There's lots of really bad C++ code available on the internet, and often the programmer does unnecessary things due to a faulty understanding of how to be "safe" in C++.)
The last area you can test with more generic interview questions.
A few questions can allow you to know a lot about a candidate:
Differences between a pointer and a reference, when would you use each?
Why would you make a destructor virtual?
Where is the construction order of a class attributes defined?
Copy constructor and operator=. When would you implement them? When would you make them private?
When would you use smart pointers? what things would you take into account to decide which?
Where else have you seen RAII idiom?
When would you make a parameter const? when a method?
When would you make an attribute mutable?
What is virtual inheritance?
What is template specialization?
What are traits?
What are policies?
What is SFINAE?
What do you know about C++Ox standard?
What boost libraries have you used?
What C++ books have you read? (Sutter? Alexandrescu?)
Some short exercises (no more than 10 minutes) about STL containers, memory management, slicing, etc. would also be useful. I would allow him to do it in a computer with a ready environment. It's important to observe the agility.
Checkout Joel's Guerrilla guide to interviewing. Seems a lot like what you are looking for.
"Write a program that receives 3 integers in the range of 0..2^32-1, and validates if they represent valid edges of a triangle".
It seems to be a simple question. The input is considered valid if the sum of any two edges is greater than the third edge. However, there are some pitfalls, that a good programmer will handle:
The correct type to use should be unsigned long. Many "programmers" will fail here.
Zero values should be considered as non-valid.
Overflow should be avoided: "if (a+b <= c) return false" is problematic since a+b may cause an overflow.
if (a <= c-b) is also bad solution since c-b may be negative. Not a good thing for unsigned types.
if (c > b) { if (a <= c-b) return false; } else { if (a <= b-c) return false; } This looks much better, but it will not work correctly if (a >= b+c).
A good programmer must be detail oriented. This simple exercise will help checking if he is.
Depending on what your organisation's pre-screening is like, assume that the person knows nothing at all about C++ and has just put in on their CV because it makes them look supertechnical. Seriously. Start with something simple, like reversing a string. I have had candidates who couldn't even write a function prototype for this !!
Do not forget to also test for code bigotry. I know I don't want anyone working for or with me that isn't a flexible and consequently practical programmer both in their attitude to the programming language, but also in their approach to problem solving.
Denying any type of preconceptions
Understanding the value of the
exceptions in any Best Practices
Being capable of refusing long term
habits in favor of something else if
the need arises
These are characteristics dear to me. The manner of testing for these is not ideal if the interviews aren't lengthy or don't involve presenting code. But showing code snippets with purposely debatable techniques while offering a use case scenario and asking the candidate how they feel about the solution is one way.
This article offers some general ideas that are relevant regardless of what language you're working with.
Don't test only the C++ and overall technical skills! Those are of course important, but they are nothing if people don't listen, don't answer properly or don't follow the commitments they made.
Check at most for the ability to clearly communicate. If people cant tell you what roughly they did in their former jobs within a few minutes, they will also be unable to report about their work at your place etc.
In a recent company we invited people for interviews in groups of about 3 people together. They were surprised, but nobody was angry about that. It was very interesting, because people had to communicate not only with us, but also with others in the same position. In case we were interested further, we arranged a second interview.
You can choose potentially problematic task and see how they approach it. Ask them to write a smart pointer for example, you'll see if they understand pointers, references and templates in one step :) Usually they are stressed so they will do mistakes, those mistakes might help you find out how good they problem solving skills are, what paths would they use to fix a mistake and so on. The only problem with this approach is that sometimes interviewee just don't know anything about the task and you would have to quickly figure out something easier. If they do perfect code you can discuss their choices but when there's nothing to look at it is depressing for both of you.
Here is my answer to a similar question geared towards C#, but notice that my answer is language agnostic. My interview question is, in fact, in C. I rarely interview a person with the goal of finding out if they can program. I want to find out if they can think, problem solve, collaborate, communicate, understand something new, and so on. In the meantime, I circle around trying to see if they "get it" in terms of the big picture of software engineering. I use programming questions because that's a common basis and an easy ruse.
Get Codility.com to screen out non-programming programmers, this will get you a limited number of mostly reasoable candidates. Sit for an hour with each of them and try to build something together (a micro web server, a script for processing some of your data, a simple GUI). Pay attention to communication skills, i.e. how much effort does it take to understand the candidate. Ask the candidate for recommendation of books related to the subject (C++ software development in your case). Follow Guerilla Guide to Interviewing, i.e. answer yourself honestly, if the person is smart and gets things done. Good luck.
Check 10 C++ Interview Questions by Tests4Geeks.
It's an addition to their pre-interview C++ test and it has really usefull questions. Many people have been working on these interview questions so it's quite balanced and has no tricky or syntax questions.
Idea is quite simple - first you weed out incompetent candidates using the test, then you use article questions in real-life interview.
Whatever you do, pairing would be a good idea. Come up with a good program and pair with the guy and work towards solving the problem. IMHO, that a very good idea
So has anybody got any suggestions?
I'd recommend getting a copy of this:
http://www.amazon.co.uk/Programming-Interviews-Exposed-Secrets-Programmer/dp/047012167X/ref=sr_1_1?ie=UTF8&s=books&qid=1252499175&sr=8-1
ie it doesn't matter whether they get the right answers or not its how they approach the problem that interests me
You could ask the candidate to come up with a UML design to a common problem. If they show you a design pattern, then you can talk through the pros/cons of the pattern. You could then ask them to produce some code for one of the classes.
This would help you determine their technical knowledge level and their communication abilities.
I do care that they have a good solid understanding of pointers as well as understanding the under lying differences between pointers and references
Linked list problems are good for determining whether a candidate has a solid grasp of pointers.
As for references, you could show them some code that does not use references correctly, and ask them to describe the problem.
e.g show them a class definition that contains a reference member variable, and the implementation of the constructor with the reference initialization missing.
I would also love to see how they approach optimisation of a given problem because solid fast code is a must, in my opinion.
I'd start off simple...
Show them a code example that passes strings to a function by value. (the strings should not be modified in the function). You should check they correct the code to pass the strings by const reference.
After this, you could show a constructor that uses assignment instead of initialization (for objects). Ask them to improve it.
Lastly, ask them simple questions about data structure selection.
e.g. When they should use a list rather than a vector.
If you feel they have a grasp of the fundamentals you could either ask how they approach optimization problems (discuss profilers etc), or ask them to optimize something less obvious.
Take a look into this C++ test. They have a questions about differences between pointers and references as you require.
Here is full list of topics:
Fundamentals: References & Pointers, Const Correctness, Explicit
Standard Library
Class Design, Overloading
Virtual Functions, Polymorphism, Inheritance
Memory Management, Exception Safety
Miscellaneous: Perfect Forwarding, Auto, Flow Control, Macros
These guys are really serious about their questions, they also made the great list of C++ interview question which you might ask your candidates:
https://tests4geeks.com/cpp-interview-questions/

Guidelines to improve your code

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What guidelines do you follow to improve the general quality of your code? Many people have rules about how to write C++ code that (supposedly) make it harder to make mistakes. I've seen people insist that every if statement is followed by a brace block ({...}).
I'm interested in what guidelines other people follow, and the reasons behind them. I'm also interested in guidelines that you think are rubbish, but are commonly held. Can anyone suggest a few?
To get the ball rolling, I'll mention a few to start with:
Always use braces after every if / else statement (mentioned above). The rationale behind this is that it's not always easy to tell if a single statement is actually one statement, or a preprocessor macro that expands to more than one statement, so this code would break:
// top of file:
#define statement doSomething(); doSomethingElse
// in implementation:
if (somecondition)
doSomething();
but if you use braces then it will work as expected.
Use preprocessor macros for conditional compilation ONLY. preprocessor macros can cause all sorts of hell, since they don't allow C++ scoping rules. I've run aground many times due to preprocessor macros with common names in header files. If you're not careful you can cause all sorts of havoc!
Now over to you.
A few of my personal favorites:
Strive to write code that is const correct. You will enlist the compiler to help weed out easy to fix but sometimes painful bugs. Your code will also tell a story of what you had in mind at the time you wrote it -- valuable for newcomers or maintainers once you're gone.
Get out of the memory management business. Learn to use smart pointers: std::auto_ptr, std::tr1::shared_ptr (or boost::shared_ptr) and boost::scoped_ptr. Learn the differences between them and when to use one vs. another.
You're probably going to be using the Standard Template Library. Read the Josuttis book. Don't just stop after the first few chapters on containers thinking that you know the STL. Push through to the good stuff: algorithms and function objects.
Delete unnecessary code.
That is all.
Use and enforce a common coding style and guidelines. Rationale: Every developer on the team or in the firm is able to read the code without distractions that may occur due to different brace styles or similar.
Regularly do a full rebuild of your entire source base (i.e. do daily builds or builds after each checkin) and report any errors! Rationale: The source is almost always in a usable state, and problems are detected shortly after they are "implemented", where problem solving is cheap.
Turn on all the warnings you can stand in your compiler (gcc: -Wall is a good start but doesn't include everything so check the docs), and make them errors so you have to fix them (gcc: -Werror).
Google's style guide, mentioned in one of these answers, is pretty solid. There's some pointless stuff in it, but it's more good than bad.
Sutter and Alexandrescu wrote a decent book on this subject, called C++ Coding Standards.
Here's some general tips from lil' ole me:
Your indentation and bracketing style are both wrong. So are everyone else's. So follow the project's standards for this. Swallow your pride and setup your editor so that everything is as consistent as possible with the rest of the codebase. It's really really annoying having to read code that's indented inconsistently. That said, bracketing and indenting have nothing whatsoever to do with "improving your code." It's more about improving your ability to work with others.
Comment well. This is extremely subjective, but in general it's always good to write comments about why code works the way it does, rather than explaining what it does. Of course for complex code it's also good for programmers who may not be familiar with the algorithm or code to have an idea of what it's doing as well. Links to descriptions of the algorithms employed are very welcome.
Express logic in as straightforward a manner as possible. Ironically suggestions like "put constants on the left side of comparisons" have gone wrong here, I think. They're very popular, but for English speakers, they often break the logical flow of the program to those reading. If you can't trust yourself (or your compiler) to write equality compares correctly, then by all means use tricks like this. But you're sacrificing clarity when you do it. Also falling under this category are things like ... "Does my logic have 3 levels of indentation? Could it be simpler?" and rolling similar code into functions. Maybe even splitting up functions. It takes experience to write code that elegantly expresses the underlying logic, but it's worth working at it.
Those were pretty general. For specific tips I can't do a much better job than Sutter and Alexandrescu.
In if statements put the constant on the left i.e.
if( 12 == var )
not
if( var == 12 )
Beacause if you miss typing a '=' then it becomes assignment. In the top version the compiler says this isn't possible, in the latter it runs and the if is always true.
I use braces for if's whenever they are not on the same line.
if( a == b ) something();
if( b == d )
{
bigLongStringOfStuffThatWontFitOnASingleLineNeatly();
}
Open and close braces always get their own lines. But that is of course personal convention.
Only comment when it's only necessary to explain what the code is doing, where reading the code couldn't tell you the same.
Don't comment out code that you aren't using any more. If you want to recover old code, use your source control system. Commenting out code just makes things look messy, and makes your comments that actually are important fade into the background mess of commented code.
Use consistent formatting.
When working on legacy code employ the existing style of formatting, esp. brace style.
Get a copy of Scott Meyer's book Effective C++
Get a copy of Steve MConnell's book Code Complete.
There is also a nice C++ Style Guide used internally by Google, which includes most of the rules mentioned here.
Start to write a lot of comments -- but use that as an opportunity to refactor the code so that it's self explanatory.
ie:
for(int i=0; i<=arr.length; i++) {
arr[i].conf() //confirm that every username doesn't contain invalid characters
}
Should've been something more like
for(int i=0; i<=activeusers.length; i++) {
activeusers[i].UsernameStripInvalidChars()
}
Use tabs for indentations, but align data with spaces
This means people can decide how much to indent by changing the tab size, but also that things stay aligned (eg you might want all the '=' in a vertical line when assign values to a struct)
Allways use constants or inline functions instead of macros where posible
Never use 'using' in header files, because everything that includes that heafer will also be affected, even if the person includeing your header doesn't want all of std (for example) in their global namespace.
If something is longer than about 80 columes, break it up into multiple lines eg
if(SomeVeryLongVaribleName != LongFunction(AnotherVarible, AString) &&
BigVaribleIsValid(SomeVeryLongVaribleName))
{
DoSomething();
}
Only overload operators to make them do what the user expects, eg overloading the + and - operators for a 2dVector is fine
Always comment your code, even if its just to say what the next block is doing (eg "delete all textures that are not needed for this level"). Someone may need to work with it later, posibly after you have left and they don't want to find 1000's of lines of code with no comments to indicate whats doing what.
setup coding convention and make everyone involved follow the convention (you wouldn't want reading code that require you to figure out where is the next statement/expression because it is not indented properly)
constantly refactoring your code (get a copy of Refactoring, by Martin Fowler, pros and cons are detailed in the book)
write loosely coupled code (avoid writing comment by writing self-explanatory code, loosely coupled code tends to be easier to manage/adapt to change)
if possible, unit test your code (or if you are macho enough, TDD.)
release early, release often
avoid premature optimization (profiling helps in optimizing)
In a similar vein you might find some useful suggestions here: How do you make wrong code look wrong? What patterns do you use to avoid semantic errors?
Where you can, use pre-increment instead of post-increment.
I use PC-Lint on my C++ projects and especially like how it references existing publications such as the MISRA guidelines or Scott Meyers' "Effective C++" and "More Effective C++". Even if you are planning on writing very detailed justifications for each rule your static analysis tool checks, it is a good idea to point to established publications that your user trusts.
Here is the most important piece of advice I was given by a C++ guru, and it helped me in a few critical occasions to find bugs in my code:
Use const methods when a method is not supposed to modify the object.
Use const references and pointers in parameters when the object is not supposed to modify the object.
With these 2 rules, the compiler will tell you for free where in your code the logic is flawed!
Also, for some good techniques you might follow Google's blog "Testing on the Toilet".
Look at it six months later
make sure you indent properly
Hmm - I probably should have been a bit more specific.
I'm not so much looking for advice for myself - I'm writing a static code analysis tool (the current commercial offerings just aren't good enough for what I want), and I'm looking for ideas for plugins to highlight possible errors in the code.
Several people have mentioned things like const correctness and using smart pointers - that's the kind of think I can check for. Checking for indentation and commenting is a bit harder to do (from a programming point of view anyway).
Smart pointers have a nice way of indicating ownership very clearly. If you're a class or a function:
if you get a raw pointer, you don't own anything. You're allowed to use the pointee, courtesy of your caller, who guarantees that the pointee will stay alive longer than you.
if you get a weak_ptr, you don't own the pointee, and on top of that the pointee can disappear at any time.
if you get a shared_ptr, you own the object along with others, so you don't need to worry. Less stress, but also less control.
if you get an auto_ptr, you are the sole owner of the object. It's yours, you're the king. You have the power to destroy that object, or give it to someone else (thereby losing ownership).
I find the case for auto_ptr particularly strong: in a design, if I see an auto_ptr, I immediately know that that object is going to "wander" from one part of the system to the other.
This is at least the logic I use on my pet project. I'm not sure how many variations there can be on the topic, but until now this ruleset has served me well.