Explicit call to constructor

I know a concept that we can call an constructor both Explicitly and Implicitly , and I tested both scenarios (as a rule, so far all my goals have been fulfilled by calling the Implicitlly constructor), but I was interested in this constructor getting an implicit call every time when we create objects , so the main reason for calling the constructor is Explicitly . What advantage or disadvantage does it provide when we call the constructor of Explicitly on top of Implicit Call ?

Example

 class integer { int m ,n; public: integer (int x , int y); }; integer :: integer (int x , int y ) { m=x; n = y; } 

Now if i call

 integer int1 = integer( 0 , 100); // Explicit Call integer int1(1,100); // implicit call 
+7
source share
5 answers

There are two different problems here, since your definition of explicit and implicit does not match the standard definition (on which most existing answers are based, written before you added your own example, which contains your own definition of explicit and implicit).

Ok, so let's first look at your definition of explicit, which will be (I suppose you call it explicit because you explicitly write the type name?):

 integer int1 = integer(0, 100); 

compared to your definition of implicit, which would be:

 integer int1(1, 100); 

In this case, the first “explicit” call does not really have any advantage over the second “implicit” call. But there is still a difference. The first actually creates a temporary object using a constructor with two arguments, which is then used to create int1 using the copy constructor. Although in practice the compiler usually optimizes this extra copy, it still won’t work if your copy constructor is private, while the second only needs a constructor with two arguments (you could even consider this a drawback).


But now the actual standard definitions are explicit and implicit. An explicit constructor call is any constructor call, well, in general, a call. Practically speaking, whenever you use the syntax in brackets () to create an object, you explicitly call the constructor, otherwise it is an implicit call to the constructor (so to speak, which is executed behind the scenes by the compiler):

 integer int1; // implicit default constructor integer int1(1, 100); // explicit two-arg constructor integer int1 = integer(0, 100); // explicit two-arg constructor, implicit copy constructor void func(integer); // function taking by-value func(int1); // implicit copy constructor 

Thus, the only constructors that can be called implicitly are the default constructor and any constructors with one argument (including copy and move constructors). A particular problem in this regard are single argument constructors that are not copy / move constructors:

 struct integer { integer(int); }; 

This allows the compiler to implicitly call the constructor for type conversion, so any int implicitly converted to integer :

 void func(integer); func(42); // implicit call to int-constructor 

To prohibit this behavior, you must mark the explicit constructor:

 struct integer { explicit integer(int); }; 

Which only allows it to be called explicitly (e.g. func(integer(42)) ) (but I think you already knew that). The advantage of this is that it does not create invisible / unwanted conversions behind the scenes, which can lead to all kinds of difficult to find problems and ambiguities regarding overload resolution. Therefore, it is common practice to flag conversion constructors (constructors without copying / moving with one argument) explicit and, most likely, also the reason that explicit conversion operators finally appeared in C ++ 11.


Thus, to summarize, according to your definition and example, there is no advantage in using integer int1 = integer(1, 100); instead of integer int1(1, 100); although that does (usually doesn't matter) the difference.

But according to standard definitions, explicit constructor calls have many advantages over implicit ones, since the only way to actually create an object explicitly is to use, well, an explicit constructor call, while implicit constructor calls are performed only behind the scenes in certain situations, they only work for zero- and designers with one argument (as Ashepler already pointed out). And explicitly marking conversion constructors as explicit has the advantage of prohibiting unwanted implicit conversions behind the scenes.

+15
source

Call constructors explicitly allow you to create an object with arguments, rather than using the default constructor.

 class Foo { public: Foo() {} Foo(int bar) : mBar(bar) {} private: int mBar; } Foo f; // Implicitly constructed with default constructor. Foo f(7); // Explicitly constructed with argument for 'bar' 
+2
source

There are three ways to call the constructor:

  • Implicitly declaring an instance of a type without initializing it
  • Also implicitly, either by initializing the instance with = , or by invoking an implicit conversion from the argument type to your class.
  • Explicit constructor call, passing arguments.

Which one you can use in a particular context depends on the constructors you invoke.

 class Foo { Foo(); // 1 Foo(int a); // 2 explicit foo(const std::string& f); // 3 Foo(int c, int d); // 4 }; 
  • This constructor will be called implicitly when declaring Foo f; . Never tries to explicitly call a constructor without arguments, since Foo f(); will declare a function!
  • This can be invoked by writing Foo f = 42; or Foo f(42) .
  • The explicit keyword prohibits implicit conversion by writing Foo f = std::string("abc"); or function_taking_foo(function_returning_string()); .
  • Since there are several arguments, an explicit version is the only one suitable.
+2
source

I am very sorry to say this because it is so perverse, but there is an additional way to explicitly call the constructor.

 class integer { int m ,n; public: integer (int x , int y); }; integer :: integer (int x , int y ) { m=x; n = y; } 

The constructor can be explicitly called by an already constructed object.

 integer i(1,100); i.~integer(); i.integer::integer(2,200); 

Here I built a (explicitly) instance of integer. Then I explicitly called it a destructor. Then I called the constructor again. I suppose you can use this idiom in testing. I do not know a single place in the standard that prohibits it. It works in Visual Studio 2010. I have not tested a really wide range of compilers.

These calls are explicit for large "explicit" values.

+1
source

If you create a function that references an object of your class, and you pass it a different type other than your object, the constructor of your class converts this type into an object of your class. Any constructor of a single argument is considered a conversion constructor. If you declare this constructor explicit, then passing a type other than your object to this function will not convert it, and the compiler will return an error

0
source

Source: https://habr.com/ru/post/923274/


All Articles