Question

I'm learning C++ at the moment, C++ Primer plus. But I just felt like checking out the cplusplus website and skip a little forward to file handling.

I pretty much know the basics of file handling coming from java, php, visual basic. But I came across a pretty weird line.

ostream os(&fb);

fb represents a filebuf. I just don't get the syntax of this, but I can figure out that it's the same as:

ostream os = &fb;

But I never really read about this way of initializing variables.

So I'm wondering. Am I just senseless and missing out a real useful feature the entire time? Is this way of initializing just old? Is it something different?

Thanks in advance.

Was it helpful?

Solution

Perhaps you should read this and this

OTHER TIPS

Both forms perform initialization. The first syntax (with ()) is called direct-initialization syntax. The second syntax (with =) is called copy-initialization syntax. They will act same in most real-life cases, but there are indeed differences between the two.

In situations when types on the left-hand side (LHS) and right-hand side (RHS) are identical (ignoring any const/volatile qualifiers), both are indeed exactly the same. The language standard explicitly states that in this case the = form is equivalent to () form.

But when the types are different (and the LHS type is a class type), these two forms will generally work differently.

  • The copy-initialization form works as follows: convert the RHS value to the temporary object of LHS type (by any means possible: standard conversion, conversion operator, conversion constructor). And then use the copy constructor of the LHS class to copy the temporary object to the LHS object.

  • The direct initialization form work as follows: just consider all constructors of LHS and choose the most appropriate one by using overload resolution.

You can immediately notice that the copy-initialization syntax unconditionally uses the copy constructor (the copying and the intermediate temporary can be optimized away, but conceptually they are there). If the LHS class has no accessible copy-constructor, the copy-initialization unconditionally becomes ill-formed, while direct-initialization might still work.

Also, the keyword explicit applied to certain constructor will affect which form of initialization is available for which combinations of types.

A small program to see when copy constructor is called and when overloaded assignment operator function is called:

#include <iostream>

using namespace std;

class test
{
    public:
        // default constructor.
        test()
        {
            cout<<"Default Ctor called"<<endl;
        }

        // copy constructor.
        test(const test& other)
        {
            cout<<"Copy Ctor called"<<endl;
        }

        // overloaded assignment operator function.
        test& operator=(const test& other)
        {
            cout<<"Overload operator function called"<<endl;
            return *this;
        }
};

int main(void) 
{
    test obj1;  // default constructor called.

    test obj2 = obj1; // copy constructor called.

    test obj3(obj2); // again copy constructor called.

    obj1 = obj2; // overloaded assignment operator function.

    return 0;
}

Output:

Default Ctor called
Copy Ctor called
Copy Ctor called
Overload operator function called

So in your case, the copy constructor of ostream is called in both the occasions.

One important benefit of function-call initialization is that they also work with constructors that take multiple arguments. For example, an fstream constructor can take two parameters:

std::fstream file("filename", ios_base::out);

Until C++0x uniform initialization is widely available, function-call initialization is the only way to handle multiple argument constructors.

From my understanding, &var is a alias for the var variable and doesn't matter which one you use.

--------Addition -----------------

The below code is taken from Stroustrup book.From this its clear that both are alias to the same variable. It also says as below.

"The semantics of argument passing are defined to be those of initialization, so when called, increment's argument aa became another name of x." Thats why I refered to &x to be alias of x.

void increment(int& aa) { aa++; }

void f() { int x = 1; increment(x); }

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top