C++ Succinctly: Visual Studio and C++

IntelliSense

If you’re using almost any of the Visual Studio keyboard mappings, typing Ctrl+J will bring up IntelliSense. In Visual Studio 2012, IntelliSense should appear automatically in C++. In Visual Studio 2010 and earlier, you need to invoke it manually.


Code Snippets

Code snippets are a new feature for C++ in Visual Studio 2012. They did not exist in earlier versions. If you’ve never used them in any language, then in a C# project, start typing “for” to begin a for loop; once IntelliSense has chosen the for snippet, press the Tab key twice and watch as a for loop appears complete with automatic fields you can edit. Use the Tab key to switch between fields. When you’re done editing the fields, press Enter. The cursor will be transported within the loop body with the field edits you made appearing as normal text.

Code snippets are particularly nice for switch statements that switch on an enum, since they will automatically populate the switch statement with all of the enum’s members.


Including Libraries

In C++, it's usually not enough to just include a header file. Normally you need to tell the linker to link against a library that implements the code declared in the header file. To do this, you need to edit the project's properties, accessible in the Project menu as ProjectName Properties...

In the properties, under Configuration Properties > Linker > Input, one of the fields is Additional Dependencies. This is a semicolon-separated list of the .LIB files you need to link against. It should end with %(AdditionalDependencies) so that any additional libraries linked via MS Build will be added.

For a typical DirectX 11 Metro-style game, for example, you might see the following:

If you receive a linker error telling you it cannot find a definition of something you are using, find the function or class on MSDN; the documentation will tell you both the header file and the library file you need.

Generating Assembly Code Files

If you want to view a very close approximation of the assembly code that your code is compiled into, in your project’s properties, under Configuration Properties > C/C++ > Output Files, set the Assembler Output option to something other than No Listing.

I’d recommend either Assembly-Only Listing (/FA) or Assembly with Source Code (/FAs). Assembly-Only Listing sprinkles enough line-number comments that you can usually cross-reference with your source code files to see what C++ code corresponds with the assembly code. That can be helpful if you want one place to see everything rather than flipping back and forth between whatever you’ve opened the .ASM file in (I use Notepad++) and Visual Studio.

Note that the generated assembly uses MASM macros (find them on MSDN). If you don’t know what a particular assembly instruction means (e.g., LEA), you can search the internet for it or download the appropriate programming manual from Intel’s site (assuming x86/Itanium), AMD’s site (assuming x64) or ARM Holding’s site (assuming ARM). If you’ve never learned any assembly, I definitely recommend doing so (try creating a simple Windows Console app).

Understanding assembly gives you a better understanding of how computers really work internally. Combine that with the knowledge that computers are all hardwired to begin executing the same code every time they are powered on (traditionally the BIOS on PCs, though that is now being replaced by UEFI), and the mystery of how and why computers work quickly begins to fade.


Terrifying Build Errors

If you come across a build error that looks completely horrible, chances are it’s from the linker. You’ll see messages like this, for instance:

All that’s saying is it cannot find a function you said it should be able to find. In this case, I added the inline keyword to a constructor function definition in the CPP file without remembering to relocate that definition to the header file. Any inline functions need to be in the header so the linker won’t hate you.

All those ??s and @@ands are just how C++ mangles names when it has compiled code into object files. Name mangling is internally consistent for the compiler in question, but the ISO/IEC standard doesn’t mandate any particular schema for name mangling. Different compilers can, and often will, mangle things differently.

Normally, if you see a horrifying build error message, chances are it’s from the linker, and it’s an unresolved symbol error. If it’s saying it can’t find something you wrote, then check to make sure your declaration in the header file matches the definition, usually in the code file but maybe in the header, or maybe you forgot to write it, or maybe you declared it inline but still have it in the code file.

An example of this is in the previous case: my SomeClass::SomeClass(wchar_t const *) constructor function (I always write const type not type const, so even that bit is reconstructed).

If it’s someone else’s function or other symbol, then chances are you didn’t tell the linker about the .LIB file that contains it.

In .NET, you just add a reference to an assembly to get both the declaration bits and the actual definition all in one. In C++, the declaration is the header file, while the definition code—excluding inline code, which needs to be in the header file too—is in a separate library. Search the MSDN library for the missing symbol and find the name of the library file you need to add.

C++ build errors can look pretty scary, especially when you receive a build error involving a template. Those can make you want to quit. But don’t. Never let the horrible error messages win. First, figure out if it’s coming from the compiler (it’ll have a C#### error number format) or the linker (LNK#### error number format).

If from the compiler, it usually means a syntax error. Check things like whether you forgot the #pragma once at the top of your header file. Another problem could be where you used something from the Standard Library (e.g., endl) but forgot to have a #using namespace std; or to prefix it with std:: (i.e. std::endl).

You can do either or both, but you must do at least one. Some things might be in a different namespace. In Visual Studio 2010, some functionality is in the stdext namespace, for example. The same goes for any namespaces in your own code.

If you aren’t having any luck on your own, go to MSDN and type the first part of the error message. You’ll probably find some helpful links to discussions on the MSDN forums, on StackOverflow, perhaps an MSDN article or an MSDN blog post—maybe even just the error code’s page itself will have the hint you need. If all else fails, post a question on a forums site: MSDN, the appropriate StackExchange site, or App Hub.

A linker error is typically an unresolved symbol, which usually means you have a mismatch in declaration and definition, have an inline outside of its header, or don’t have the right library added to the project’s extra dependencies in the project’s linker options. If it’s something else, try the strategies from the previous paragraph; they apply just as well to linker errors as to compiler errors.

Conclusion

If you're doing a lot of C++ development, then Visual Studio is certainly an IDE (Integrated Development Environment) worth considering. It has a lot more to offer than what's covered in this article, so I encourage you to give it a try and explore it's wide range of features.

This lesson represents a chapter from C++ Succinctly, a free eBook from the team at Syncfusion.
Tags:

Comments

Related Articles