Am I using C++ pointers and references correctly?
I'm not sure whether this should be reviewed yet or not.  I can't decide what critiques are things that you haven't learned yet but will, and things that you haven't learned yet and might not.  (Also, there's a handful of errors that should have been found with basic testing.)

Anyway here's a few things that jumped out at me:


There's no notion of const correctness at all in your code
system("pause") is bad -- it's slow, and implementation dependent

if you want to see the output, run it in a shell directly instead of using system("pause") as a hack

When pointerLastName is NULL, string LastN = *pointerLastName; is undefined behavior and will probably crash.
if(LastN == "NULL" ) makes no sense

a NULL pointer being dereferences does not turn into the string "NULL" -- it crashes (typically)

Your do {} while() loop in the second program is broken
using namespace std; pollutes the global namespace.  It's typically better to just qualify it directly like std::string or import specific things using std::string;.

In small, simple programs, it tends to not matter.  It can become a bad habit though.
#include "iostream" should be #include &lt;iostream&gt; -- I'm actually a bit surprised that compiles.



Also, for what it's worth, I wouldn't use pointers in either of these two programs.  References are a better choice.  Obviously this is a learning exercise though, so this critique doesn't really apply.



Based on our comments back and forth, there seems to be some confusion surrounding pointers.  I'm not sure if it's me misunderstanding what your saying, or a misunderstanding of pointers, but either way, I figure I'll elaborate a bit.

if(LastN == "NULL" )


That is checking if LastN is equal to the string "NULL".  That is not the same thing as checking for a NULL pointer:

string* pNullStr = NULL;
string nullStr = *pNullStr; //undefined behavior (almost certainly a crash)


The only way a string is going to have a value of NULL is if it is actually set to NULL:

string ns = "NULL";
if (ns == "NULL") {
    //this will happen
}


In other words, your userNames function isn't prompting the user for a last name only "if the caller passes in a NULL pointer for the last name" (as your instructions say).  What it's doing is prompting for a last name only if the caller passes in a string (not a pointer to a string) equivalent to "NULL".

Based on your code, the only way a last name is going to be prompted for is if you type "NULL" in when prompted for a last name (in the main code).

Perhaps this was by design, but it directly contradicts your exercise instructions.



Also, while I'm at it with the editing, if you wanted to be really careful, you could check all of the input operations.  In fact, really you should always check, but in a program this simple, it would be a bit of a pain.

To clarify:

cout &lt;&lt; "FIRSTNAME: ";
cin &gt;&gt; firstName;


That can fail.  What if the user writes EOF or if the user pipes in an empty file?  That means the read is going to fail.

if (!(std::cin &gt;&gt; firstName)) {
    std::cerr &lt;&lt; "Fatal error: reading last name failed";
    return EXIT_FAILURE; //(defined in cstdlib)
}




On a stylistic note, not sure why I didn't spot this before: if your loop in userNames is actually what you meant it to be, you can write it much more cleanly:

while (lastN == "NULL") {
    std::cout &lt;&lt; "Again what is your last name? ";
    std::cin &gt;&gt; lastN; //Once again, this should be checked
}