I both agree and disagree with frob here; he's dead wrong in that you should never use 'friend' but he's very right in his reasoning for why you shouldn't use it.
'friend' is a key part of C++ and - when used appropriately - is a very intentional part of good design.
The difference is this: if you are writing some code and decide that you need access to a class's private implementation and you then go and modify that class to add a friend, you are being naughty and should be punished.
If you are writing a class and decide that you need to expose a key operation of that class as a free-standing function that is otherwise intimately linked to that class and nothing else and so use a friend function declaration, you are writing C++ the way it's intended to be written.
Example:
class MyFoo {
friend UnrelatedBar; // BAD BAD BAD: friend to an unrelated type
int private_int = 0;
};
class UnrelatedBar {
peekAtFoo(MyFoo& foo) { foo.private_int = ... } // BAD BAD BAD: touching someone else's privates is totes inapprops
};
compared to:
class MyFoo {
int private_int = 0;
friend void coreFeatureFoo(MyFoo& foo); // JUST FINE: this is a free function that is an intentional part of the class
};
void coreFeatureFoo(MyFoo& foo) { foo.private_int = ... } // JUST FINE: touching your own privates is perfectly natural
Syntactically, there's no difference. It's all in the intent. As a very very rough guideline: if you're writing your friend function implementation in the same .h or .cpp file that you write your member function implementations, you're making correct use of friend. If you're writing the friend implementations in different files from the class itself, you're abusing the language is horrible ways, you are very naughty, and you need to be beaten with a copy of the ISO standard.
The advantage of a free function is that it is generically composable. The disadvantage is that it is not polymorphic. e.g., code relying on member functions and interfaces requires that your classes all implement that interface. If the class is external to your codebase, you either have to go modify the external code or you have to wrap it. With free functions, you can just add a new function that operates on that type (but note that since this is an external addition, _is is not a friend function_ - that's the whole point).
If you have a free function that needs to operate on a class you did not write then it should only operate using the public members of that class. Friend functions are only for free functions that are intimately part of the class's intended public members.
C++ relies heavily on this paradigm. Extension points are generally defined as free functions. Some of the default implementations of those extension points look for member functions, some don't/can't. If you use only the member function extension points you will be very limited in what can be extended (e.g., std::begin(x) is a free function because x.begin() can't be implemented where x is not a class type like C arrays; std::swap(x, y) is a free function because not every class has a swap(y) member function but every type that is copyable is swappable whether or not the swap member is present).
All that said, C++ programmers tend to write everything as member functions (even when the function has no need to be a member function) just to make our IDEs/tools easier to use (because they autocomplete and enable inspection of members, but generally aren't helpful with free functions). Proposals like N4474 were written partially to help address this issue, but sadly we're not getting anything like that until at least C++20 if not later/never.