c++学习笔记分享--explicit关键字

c++学习笔记分享--explicit关键字
日常分享整合的学习笔记首先explict中文意思是 清楚明白的易于理解的明确的直言的 ;显式在编程中explicit用来告诉编译器“不要偷偷用这个构造函数做隐式类型转换1.先看一个反面例子没有 explicit假设有一个类class Number { public: Number(int x) { // 只有一个参数的构造函数 value x; } private: int value; }; void printNumber(Number n) { // 假装打印一下... } int main() { printNumber(42); // 这里发生了甚么 }printNumber(42);在这里你本来想传入一个Number类给printNumber但你传错了而且这里发生了隐式类型转换等价于Number n 42; //这个是可以编译过的可以试一下并输出一下value成员变量结果是42 //相当于调用构造函数 Number n(42);这很奇怪对吧因为编译器看到printNumber需要Number对象但你传了一个int恰好是Number类对应的构造函数参数,于是它会自动调用Number(int)构造函数把42变成Number(42)。这就是隐式类型转换。加上 explicit 之后class Number { public: explicit Number(int x) { // 加了个 explicit value x; } private: int value; }; void printNumber(Number n) { /* ... */ } int main() { // printNumber(42); // 这行现在会报错 printNumber(Number(42)); // 必须显式构造这样写才行 }加了explicit后编译器不会再偷偷帮你把42转换成Number你必须自己明确写出构造过程。这让代码意图更清晰也避免了一些隐蔽的错误。2. 多参数构造函数C11 起从 C11 开始explicit也可以用在多参数构造函数上。它的作用是禁止使用花括号初始化列表进行隐式转换。class Point { public: explicit Point(int x, int y) : mx(x), my(y) {} //初始化列表 private: int mx, my; }; void draw(Point p) {} int main() { draw({1, 2}); // ❌ 错误不能隐式转换 draw(Point{1, 2}); // ✅ 正确显式构造 }注意这里说的是花括号初始化列表​{1, 2}这种写法。如果是draw(Point(1, 2))圆括号构造本来就没有隐式转换的问题。3.常见疑惑与陷阱疑惑 1explicit 会影响拷贝/移动构造函数吗不影响。​explicit只影响普通构造函数和转换运算符。拷贝构造函数和移动构造函数即使加了explicit也不影响它们正常的拷贝/移动行为但一般没人给它们加。class Foo { public: explicit Foo(int) {} // 普通构造禁止隐式转换 // 拷贝构造函数不需要 explicit Foo(const Foo) default; };疑惑 2explicit 和 default / delete 一起用可以。比如你想禁止某些隐式转换但仍然保留默认构造class Bar { public: explicit Bar(int) default; // 显式构造且使用默认实现 Bar(double) delete; // 完全禁止 double 类型的构造 };疑惑 3explicit 到底能不能提高性能通常不能。​explicit不影响运行时的性能它只影响编译器的行为——是否允许某种写法通过编译。所以不用担心加了explicit会让程序变慢疑惑 4什么时候应该不加 explicit很少见但有几种情况可以考虑不加包装类比如一个类只是对底层类型的一层薄包装而且经常需要和底层类型互操作。例如std::string_view可以用const char*隐式构造。数值类型比如你自己写的BigInteger类允许int隐式转换成它可能会方便一些。仿函数/适配器某些设计模式里隐式转换反而让代码更简洁。不过作为新手先一律加explicit等你真的遇到需要去掉的情况再改这样最安全。4.什么时候用建议所有单参数构造函数都建议加上explicit除非你有非常明确的理由需要隐式转换这种情况极少。比如标准库里的std::vector有一个explicit vector(size_t count)就是为了防止你不小心写出这样的代码std::vectorint v 10; // 如果没有 explicit这行可能就编译过了但语义很奇怪End.............如果这篇笔记对你有帮助留下赞蟹蟹