Click here to Skip to main content
15,891,689 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
What is the advantage of implicit assignment over explicit assignment?
Consider the below example:
C#
class base
{
    int b;
public:
    base()
    {
        b = 0;
    }
    base(int x):b(x)
    {
    }
};
int _tmain(int argc, _TCHAR* argv[])
{
    class base bobj(44);

    return 0;
}


Normally I have seen variables in class are initialized with implicit assignment even for the standard data types as shown above.
Why it is preferred so?

The explicit assignment shown below also does the same thing:
C++
base(int x)
{
        b = x;
}


Then why is implicit preferred over explicit?
What is the advantage of base(int x):b(x) over
base(int x)
{
b = x;
}
?
Posted

 
Share this answer
 
Comments
rupeshkp728 21-Nov-11 9:17am    
Thanks Lan for the nice link.
LanFanNinja 21-Nov-11 9:28am    
You're Welcome
Hi,

I recommend you read Scott Meyer's "Effective C++" and "More Effective C++". You can't call yourself a C++ programmer until you do. He explores how to write low maintenance, high quality code and definately dicusses your query above.

HTH.
 
Share this answer
 
Comments
rupeshkp728 21-Nov-11 9:04am    
Thanks Min for suggesting me the book.
For plain old data (like int) members the generated code is nearly identical.
The advantage comes when b is not plain old data.
In that situation the generated code would have a default construction followed by an assignment instead of an explicit construction. So member initialisation results in less code.
The only warning or recommendation I can give you for that case is that you should take care to ensure that the member initialisation doesn't assume a construction order for the members.
 
Share this answer
 
Comments
rupeshkp728 21-Nov-11 9:19am    
Thanks David.
My doubt about the standard variables is clear from your statement "For plain old data (like int) members the generated code is nearly identical."
The correct term to use here is initializer list or initialization list. Since minkowski already pointed to Scott Meyer in a previous Solution, here is a thread referencing his books on this topic:
http://www.cplusplus.com/forum/articles/17820/[^]
 
Share this answer
 
Comments
rupeshkp728 21-Nov-11 9:16am    
Thanks Stefan for the link.
It clears all my doubt.
Its more efficient to use the initializer list. Performance difference is negligible when you compare POD types and complex types but still using an initializer list is more elegant. Members get initialized even before the body of the constructor gets executed.

There are cases where an initializer list is mandatory say like when you have constants or references in your class.

Also if you have a initializer with the same name as the data member the compiler will know how to resolve these names.

class A{
int a;
public:

A(int a):a(a){}
};
 
Share this answer
 
implicit means that the compiler is free to automatically reinterpret an expression by converting an operand to another type through an implicit constructor. explicit means that this is forbidden.

Consider these examples:
C++
class Complex {
private:
  double im_;
  double re_;
public:
  Complex(double re) : re_(re) {} // implicit
  Complex(double re, double im) : re_(re), im_(im) {} // not implicit
  explicit Complex(double* vec) { re_ = vec[0]; im_ = vec[1]; } // explicit
  // ...
};
void Foo() {
  Complex ca(1.0), cb(0.0, 1.0);
  double mydouble = 3.14;
  double * ar = &mydouble;
  double va[] = { -1.0, 1.0 };
  Complex cc = ca + Complex(va); // explicit constructor required!
  Complex cd = cc - 3.0; // implicit constructor called
  Complex ce = cb + ar; // error: cannot convert double* to Complex; explicit construction required
}


The last line will cause a compiler error, but only because I added explicit to the appropriate constructor. If I hadn't, a simple type or other oversight might let the compiler accept this line, even though it doesn't make much sense. The keyword ecplicit here helps us to make sanity checks at compile time.


P.S.: I just noticed you didn't actually talk about implict and explicit constructors using the explicit keyword, after all. I hope my response can still shed some light on a somewhat related area ...
 
Share this answer
 
v4
Comments
rupeshkp728 21-Nov-11 9:11am    
Thanks Stefan ffor the reply.
Yes I am talking about benefits of implict and explicit assignemnts( not constructors ) in case of STANDARD variables.
I just remembered one other important property of initializer lists which could influence code semantics, so I thought I'd mention it.

Consider the following code:
C++
class Base {
private:
  double x_;
  int y_;
public:
  int virtual MyMagicNumber() const;
  Base(double x) : x_(x) {
     y_ = MyMagicNumber();
  }
};

class derived : public Base {
private:
  int i_;
public:
   virtual int MyMagicNumber() const { return i_+1; }
   derived(int i) : Base((double(i)/2.0) {
      i_ = i; // version 1
   }
};
void Foo() {
   derived d(3);
}

Upon calling the constructor of derived, the following happens:

0. if no other instance of class derived has been created before, vtables will be created in memory
1. Memory gets allocated. This memory is uninitialized, it may not even be set to 0.
2. Base gets initialized, because it's on the initializer list
3. Base::x_ gets initialized to 1.5, because it is on the initializer list of Base::Base(double)
4. The code of Base::Base(double) gets executed
5. MyMgicNumber() gets called, via the vtable, where it gets resolved to derived::MyMagicNumber()
6. derived::MyMagicNumber() reads derived::i_ and then returns i_+1
7. Base::Base(double) initializes Base::y_ with the result from MyMagicNumber(). The constructor is done.
8. With Base::Base(double) done and nothing else on the initializer list, the code from derived::derived(int) finally gets executed
9. derived::i_ gets initialized to 3


So, the very last thing that happens during construction is the initialization of derived::i_, but some time before that, it already gets read! As a result, the state of Base::y_ is undefined! Of course, the true problem is that you shouldn't call virtual functions in your constructor code, but you can fix it, easily, by putting i on the initialization list as well:
C++
derived(int i) i_(i), Base((double)i/2.0) {} // version 2

There. This moves the initialization of derived::i_ right up to position 2, and now the following initialization of Base::y_ will be well-defined!

In short, the initialization list is the only way to initialize class members before calling base class constructors! What you need to keep in mind is initialization order:
- First the initialization list, left to right (this may include direct base classes)
- Second any constructors for base classes not already listed on the initialization list (don't ask for virtual base classes, I'd need to look that up)
- Last the actual code in the constructor body
 
Share this answer
 
Comments
rupeshkp728 21-Nov-11 15:07pm    
Great example Stefan.
Thanks a lot for your inputs.
Philippe Mori 21-Nov-11 18:47pm    
That solution is misleading. There are 2 major errors in what you said:

1) Functions called directly from a constructor are not called virtually.
2) You cannot initialize a member of the derived class before calling the base class simply with initializer list. The order depends on the declaration order.
Stefan_Lang 22-Nov-11 5:57am    
Thanks for posting that link in the other thread - I think you meant to post it here: http://en.allexperts.com/q/C-1040/Initialization-order-c.htm

I've worked from memory based on another very good article on initialization order, which unfortunately I couldn't find. after some googling I could locate it here: http://www.google.ch/url?sa=t&rct=j&q=virtual+inheritance+order+of+initialization&source=web&cd=5&ved=0CEcQFjAE&url=http%3A%2F%2Fwebcourse.cs.technion.ac.il%2F236703%2FSpring2005%2Fho%2FWCFiles%2F09F-C%2B%2B-Addendum-Multiple-and-Virtual-Inheritance-in-C%2B%2B-x4.pdf&ei=rH7LTuvIFIjk4QTk8Ik9&usg=AFQjCNF2_1Xn6uMQSX6qWeVdVtH0ZeAHZQ
(I hope that link works, it's a bit longish...)

Anyway, it seems I greatly misremembered some parts of it. I suppose i could fix the example to something more meaningful, but with, now, two links to good articles I suppose that is hardly required... ;)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900