class Widget {
public:
Widget(int i, bool b); // as before
Widget(int i, double d); // as before
Widget(std::initializer_list<long double> il); // added
…
};
Widget w1(10, true); // uses parens and, as before,calls first ctor
Widget w2{10, true}; // uses braces, but now calls std::initializer_list ctor (10 and true convert to long double)
Widget w3(10, 5.0); // uses parens and, as before, calls second ctor
Widget w4{10, 5.0}; // uses braces, but now calls std::initializer_list ctor (10 and 5.0 convert to long double)
例子:
class Widget {
public:Widget(int i, bool b); // as before
Widget(int i, double d); // as before
Widget(std::initializer_list<long double> il); // as before
operator float() const; // convert to float
};
Widget w5(w4); // uses parens, calls copy ctor
Widget w6{w4}; // uses braces, calls std::initializer_list ctor (w4 converts to float, and float converts to long double)
Widget w7(std::move(w4)); // uses parens, calls move ctor
Widget w8{std::move(w4)}; // uses braces, calls std::initializer_list ctor(for same reason as w6)
class Widget {
public:
Widget(int i, bool b); // as before
Widget(int i, double d); // as before
Widget(std::initializer_list<bool> il); // element type is now bool
…//no implicit conversion funcs
};
Widget w{10, 5.0}; // error! requires narrowing conversions
例子:
class Widget {public:
Widget(); // default ctor
Widget(std::initializer_list<int> il); // std::initializer_list ctor
… // no implicit conversion funcs
};
Widget w1; // calls default ctor
Widget w2{}; // also calls default ctor
Widget w3(); // most vexing parse! declares a function!
Widget w4({}); // calls std::initializer_list ctor with empty list
Widget w5{{}}; // ditto
例子:
std::vector<int> v1(3, 4);// [4, 4, 4]
std::vector<int> v1{3, 4};// [3, 4]
Item 8
In c++98:
void f(int); // three overloads of f
void f(bool);
void f(void*);
f(0); // calls f(int), not f(void*)
f(NULL); // might not compile, but typically calls f(int). Never calls f(void*)
.
nullptr’s advantage :
1.it doesn’t have an integral type, it doesn’t have a pointer type,
nullptr’s actual type is std::nullptr_t.
e.g.
f(nullptr); // calls f(void*) overload
2.improve code clarity,
2.1when autovariables are involved,
e.g.
auto result = findRecord( /* arguments */ );
if (result == nullptr) // rather than using (result == 0)
{…}
2.2when templates enter the picture
e.g.
decltype(auto) lockAndCall(FuncType func, MuxType& mutex,PtrType ptr)
auto result1 = lockAndCall(f1, f1m, 0); // error
auto result2 = lockAndCall(f2, f2m, NULL); // error!…
auto result3 = lockAndCall(f3, f3m, nullptr); // fine