C++ Assumptions - c++

Once I saw a way in C++ to assume something, for example:
int x=7;
assume (x==7);//if not right a red error will appear and program will end.
Can someone please tell me what was the exact code for that? I have done a lot of research but found nothing since I forgot the original phrase.
(I want to use this for debugging)

You are probably looking for assert, cf. https://en.cppreference.com/w/cpp/error/assert.
There is also static_assert, which does checking during compile time.
There was a proposal to add more pronounced system of "assumptions" to C++, called contracts (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1866.html), but its introduction to the language is postponed. If you are learning, you don't really need to read the document under that last URL.

Related

Meaningful diagnostic messages

Looking at several posts, I get a feel that many of the questions arise because compilers/implemenetation do not emit a very meaningful message many times (but not always). This is especially true in the case of templates where error messages could be at the least very daunting. A case in point could be the discussion topic
Therefore, I would like to understand a few things:
a) Why is it that compilers are sometimes unable to give more meaningful/helpful error messages? Is the reason purely practical or technical or is there something else. (I don't have a compiler background)
b) Why can't they give a reference to the most relevant conforming C++ Standard Verse/section, so that developer community can learn C++ better?
EDIT:
Refer the thread here for another example.
EDIT:
Refer the thread here for another example.
The fundamental problem is that compiler diagnostics deal with things you haven't written.
In order to give you a meaningful error message, the compiler has to guess what you meant, and then tell you how your code differs from that.
If you're missing a semicolon, the compiler obviously can't see that semicolon anywhere. Of course, one of the things it can do is to guess "maybe the user is missing a semicolon. That's a common mistake, after all". But where should that semicolon have been? Because you made an error, the code can't be parsed into a syntax tree, so there's no clear indicator that "this node is missing from the tree". And there might be more than one place where a semicolon could be inserted so that the surrounding code would parse correctly. And moreover, how much code are you going to try to parse/recompile once you've found what might be the error? The compiler could insert the semicolon, but then at the very least it has to restart parsing of that block of code. But maybe it introduced errors further down in the code. So maybe the entire program should be recompiled, just to make sure the fix the compiler came up with was actually the right one. But that's hardly an option either. It takes too long.
Say you have some code like this:
struct foo {
...
}
void bar();
what is the error here? Looking at it, you and I would say "you're missing the semicolon after the class definition". But how can the compiler tell? void could be a typo. Perhaps you actually intended to write the name of an instance of type foo. then the real error would be that it is followed by what now looks like a function call.
So the compiler has to guess. "This looks like it could have been a class definition, and what comes after it looks like it the name of a type. If that is true, the user is missing a semicolon to separate them".
And guessing isn't a very precise science. And matters are further complicated because every time the compiler tries to be clever and makes a guess, it's only going to add confusion if the guess is wrong.
So sometimes, it might be better to output a short, terse message saying only what we're sure of (say, that a class definition cannot be followed by a type name). That's not as helpful as saying "you're missing a semicolon after the class definition", but it's less harmful if the compiler guesses wrong.
If it tells you you're missing a semicolon, and the error was actually something else, it's just misleading you. So maybe a terse and less helpful error message is better in the worst case, even if it isn't as nice in the best case.
Writing good compiler errors isn't easy, especially not in a messy language like C++.
But when that is said, some compilers (including MSVC and GCC) could be a lot better. I believe that better compiler diagnostics are one of the primary goals of Clang.
A common mistake that people make when
trying to design something completely
foolproof is to underestimate the
ingenuity of complete fools.
--- Douglas Adams
I'll try to explain some rationale behind diagnostics (as the standard calls them):
a) Why is it that compilers are sometimes unable to give more meaningful/helpful error messages?
Compilers are bound to obey the standard. The standard defines more or less everything that the compiler needs to diagnose (e.g. syntax errors) because these are invariants, stuff that the vendor needs to document (called implementation defined as the vendor has some leeway as to how to document), stuff they call unspecified (the vendor can get away without documenting) and then undefined behavior (if the standard can't define it, what error message can the compiler possibly spit out?).
b) Why can't they give a reference to the most relevant conforming C++ Standard Verse/section, so that developer community can learn C++ better?
Not everyone has a copy of the
standard.
Instead, what the compiler tries to
do is group errors by categories and
then fixes a human-understandable
error message that is generic enough
to handle all sorts of errors in that
category while still being
meaningful.
Also, not all compilers are standards
compliant. Sad, but true.
Some compilers implement more than
one standard. Do you really expect
them to quote C&V of 3 standards
texts for a simple "missing ;"
error?
Finally, the standard is terse and
less human readable than the
committee would like to think (okay,
this is a tongue-in-cheek remark but
reflects the state of affairs pretty
accurately!)
And read the quote at the top once more ;)
PS: As far as template error messages are concerned, I have to offer the following:
For immediate relief, use STLFilt
Pray that Concepts make their way into the next standard
There are some compilers that are better than others. The compiler from comeau I've heard gives significantly nicer errors. You can try it out at http://www.comeaucomputing.com/tryitout/
Compiler authors aren't chosen for their English abilities, and don't choose their work for the writing opportunities.
That said, I think error messages have consistently improved over the last decade. With GCC, the problem is usually sifting through too much information. The discussion you linked was about a "no matching function" message. That's a common error which is usually followed by a torrent of candidate functions.
Being referred to the standard's rules on overload resolution would be possibly even counterproductive in this case. To resolve the issue, I'll find the candidate I want and compare it to the call site. 99% of the time, I want a simple no-frills match, and 99% of the sophisticated resolution machinery won't apply. Having to review the resolution rules in the standard often indicates you're getting into deep doo-doo.
I think only a minority of programmers are really inclined or fully able to navigate and interpret the ISO standard, anyway.
On the bright side, there are always avenues to contact the authors of any actively-maintained compiler. If you have any kind of suggestion for improved wording, send it in!
IMHO, often times what matters is not the text of the message, but the ability to relate it to the source. The C++ compiler in VS2005 seems to show error messages indicating the file where the error occurred, but not the file it was included from. That can be a real pain when e.g. a mistake in one header file causes compilation errors in the next one. It can also be difficult to ascertain what's going on with preprocessor macros.
A factor not mentioned in the other answers I've read: C++ compilers have a very complicated job as is, and don't further complicate it by classifying the code they're compiling into "expected" stuff and "unexpected". For example, we as programmers understand that std::string is a particular instantiation of std::basic_string with various character types, traits, allocators - whatever. So, when there's an error we just want to know it involves a string and not see all that other stuff. But, say we're asked to debug an error message a client encountered when using our library. We may need to see exactly how a template has been instantiated in order to see where the problem is, and simply seeing some typedef that's inside their code - that we may not even have access to - would make the error messages useless. So, programmers at different levels in the software stack want to see different things, and most compilers don't want to buy into guessing about this or allowing customisations, they just spit everything out and trust the programmer will quickly learn to focus in on the stuff at the level they need to. Most of the time, programmers quickly learn to do that, but sometimes it's harder than others.
Another factor is that sometimes there may be many small variations on the erroneous code that would all be valid, so it's impractical for the compiler to know what the programmer intended and display a message about that delta. Programmers however are often unaware of the other ways the code might almost have made sense, and just think the compiler is dumb for not seeing it from their perspective.
Cheers,
Tony

Tool to identify the similarities in logic between a function of C and C++

Is there a tool in either Linux/Windows that would enable us to determine if a logic of the particular function in C is same as that of a particular function in C++ ?
In general, the equivalence of Turing machines is undecidable, so no.
If you are just talking of control structures, if/else, blocks of code, swtich/case, while, for, etc AND if you are willing to be able to accept "gettign a good feel for it", rather than 100% accuray, then a picture may be work a thousand words, and you might look at a code to flowchart program.
I won't recommend any, as I don't know them well enough (but have always wanted to try them out, espcially if round trip. It might not be easy to find something free. In general, you will see something like this ... alt text http://www.ezprog.com/wp-content/uploads/flowchart.gif
is that what you have is mind? Do it for both C and C++ versions, and you can get a rough feel for similarity of logic.
Perhaps you can tell us a little more what exactly you are looking for? Help us to help you? Thanks.
You can imagine a tool that compares the structure of ASTs after the compiler has done the initial conversion to abstract representation or after one of more optimization passes.
This would probably
Miss some real matches (i.e. generate false negatives)
Identify some bogus matches (i.e. generate false positives)
With tuning you could force the second case to be more common. I have no feel for how good it would have to be to be useful as a front end to a vgrep process.
But it get worse, because you've asking for a cross-language implementation, and that will make it harder. Still, gcc uses the same abstract representation for everything, so it is not beyond imagining.
That said, I know of no such tool.
I think there is such a tool, called an assembly listing.

Is it possible for programmer to analyze unknown code fast?

I got a task related to ANCIENT C++ project which hasn't any documentation, comments at all and all code/variables is written in foreign language. Do I have a chance to analyze this code in a 1 working day and make a design/UML to create new features? I have been sitting around for 3 hours already and I feel so frustrated... Maybe somebody also had same problem? Any advice?
BR,
I suspect the biggest issue may be the fact that it's in a foreign language. You can use various static code analysis tools to try and understand what's going on, but if everything is presented in an unfamiliar language then that's still no use. Your first step (I believe) is to find someone who can speak this language and get them to translate as you go...
1) Use Doxygen , You can configure doxygen to extract the code structure from undocumented source files.
2) Use source Insight, Source Insight is an advanced code editor and browser with built-in analysis for C/C++, C#, and Java programs
Short answer, no - you probably don't have a chance to understand the code in one day. Reading/maintaining code is one of the hardest things to do, especially when it's lacking documentation. The fact that the code is in a foreign language (!) makes it even harder.
Sounds like you are on a very restricted (unrealistic) time-budget, but Working With Legacy Software is a good book if you're working with legacy systems. If you are planning to keep adding new features to the legacy system it's your responsibility to make your management aware of the scope of the operation. Or at least try.
Under this time constraint (1 day) it may or may not be doable depending on the size of the project - if its a few hundred lines of code then for sure. If its a serious project with several tens of thousands code lines, then likely no.
The first thing you need to know is what is this program supposed to do at all. If you have no idea what it does and how it does it, then analyzing the code will give you the answer but it will be a long and frustrating task. So my first suggestion would be to get yourself familiar with the outer workings of the software - what does it supposed to do and generally how it is supposed to do it. If you are doing it as part as your work then you should be able to get someone to walk you through using the program - even if its UI is in a foreign language (which I hope it doesn't, even if the code is written by a foreign language speaker).
Once you know what the software is attempting to do, then it should be fairly straight forward (even if lengthy and daunting) to rewrite all the comments in your own language for you to understand. I suggest doing so in a bottoms-up approach: its easier to understand the small and trivial things a program does, then to understand the top-level logic - and a lot of trivial things in order make up the logic of the software.
Only once you understand - to a large degree, anyway - the inner workings of the program you may write its functional spec and work on features.
Non-free way on Windows:
You can use CppDepend. This application is able to parse your visual project or your source files. It gives you a lot of information like dependency trees. You can try the trial (Maybe it will be enough for what you have to do).
Free way multi-platform:
You can use doxygen with a special configuration (extract code structure from undocumented code) and analyze the result.
I was quite happy with a tool called Understand (15-day eval license available) for this kind of task. However, I agree with Guss that the time you'll need depends a lot on the size of the code, and one day is probably just enough for a small program.
cscope & ctags are a must when I do my own code, and even more when looking to other's code.
You may also try this ::
http://www.sgvsarc.com/product_crystalflow.htm

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.

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.