1)
|
f.read( (char*)(&x), sizeof(x) )
|
The parameters to the read function are, in order, a pointer to the memory into which to read and the [maximum] number of bytes to read.
Since x is of type long, you are correct in thinking that &x is a pointer to long. Since the read function takes a char* as its first argument, the pointer &x has to be typecasted to the correct type. This is what the (char*) does. It says to the compiler that the expression &x should be considered a char* rather than a long*. sizeof( x ) is a compile-time constant that will evaluate to the number of bytes of memory occupied by x (which is type 'long') and thus is probably 4 or 8, depending upon your CPU/OS.
You are correct in thinking that it is dangerous to change pointer types, but perhaps no more than changing non-pointer types also. The syntax (some-type-here)( expression ) is a C-style cast that is used to defeat C/C++'s typechecking system ostensibly because the programmer "knows better" what the type should be. In good programming, it is best to avoid these kinds of casts for reasons of safety as you mentioned.
2)
You are right. To understand function objects you have to know a little about object-oriented programming. A function object is a class (or struct) that contains a function call operator. Eg:
1 2 3 4
|
struct is_less_than_four {
bool operator()( int x ) const
{ return x < 4; }
};
|
You can "call" this function like this:
1 2 3
|
is_less_than_four obj; // Instantiate object
if( obj( 3 ) ) // <-- here's how you call it
cout << "3 is less than 4" << endl;
|
Note that the syntax for calling it is the same as calling an ordinary function (hence the name function call operator). The use of this is to turn objects into things that can be called like functions. Why is this useful? For generic programming purposes.
So less<int> is one of these function objects. It just happens to be templated. My example above was limited to int; less is not. Hence list<int>() instantiates a less function object for ints.
Set uses this to determine the ordering in which to insert elements into the set. Why is this important? Because it controls the order in which I see the values if I walk from begin() to end(). By default, set uses less<int>, which means that walking from begin() to end() would produce a strictly increasing sequence.
To answer your other questions: set always needs a "function" to compare elements. As I mentioned, the default if you don't specify it is less, and for almost all purposes this should suffice. And no, technically it does not need to be the same, though I can't imagine a scenario in which it is useful to make it different. Given the declaration set< T1, less< T2 > > T1 must be convertible to T2.