Implicit conversion is a convenience that C++ offers to programmers. However, sometimes this can cause unexpected results. It is always a good rule of thumb to be explicit when expressing your intent. The following code snippet demonstrates how implicit conversion (both narrowing and widening) can be useful and can avoid casting between data types manually.

#include<iostream>

int main()
{
  int num = 10.2;    // Implicitly converts float to num which is fine at the cost of loosing precision
  float radius = 10; // Implicity converts int to float.
  std::cout << "Num: " << num << " Radius: " << radius << std::endl;

  size_t sz = -1; // size_t is a type which stores size of anything i.e positive numbers
  std::cout << "Size: " << sz << std::endl;
  /** Output
    Num: 10 Radius: 10
    Size: 18446744073709551615
  */
 return 0;
}

As we can see here, the conversion can cause surprising results. For some reason, if someone happens to assign a negative number to size_t, it will convert it to the maximum positive number size_t can store in the system. Here, size is equal to 2^64 - 1. To avoid these surprises, prefer to use initializer lists. The code below does not compile, and it is a good thing as it will surface the narrowing conversion and one can take action. Compilation time error is always better than runtime bugs. Note that float radius{10}; works fine. This is because widening conversion generally increases precision and is considered acceptable.

int main()
{
  int num{10.2};
  float radius{10};
  size_t sz{-1};
  /**
   * Compilation error 1: type 'double' cannot be narrowed to 'int' in initializer list
   * Compilation error 2: constant expression evaluates to -1 which cannot be narrowed to type 'size_t'
  */
  return 0;
}