首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Chapter 3: Moving to Modern C++

::initializer_list参数,在使用花括号初始化时,编译器会强烈地偏向于调用使用std::initializer_list参数的重载构造函数 class Widget { public...construction 编译器非常偏向选择std::initializer_list构造函数,以至于即便最匹配的std::initializer_list构造函数不能被调用,编译器也会优先选择它...只有当没有办法在花括号初始化的参数类型和std::initializer_list的参数类型之间进行转换时,编译器才会重新选择正常的构造函数 class Widget { public:...::initializer_list构造函数时,此时调用空的花括号初始化,编译器会解析为调用默认构造函数,而要解析成std::initializer_list构造函数,需要在花括号中嵌套一个空的花括号进行初始化...它们的值也许会被放在只读内存区中,它们的值也能被用在整型常量表达式中,例如数组长度,整型模板参数,枚举值,对齐指示符等等 当constexpr函数使用constexpr对象时,它们会产生编译期常量,如果

1.8K60

真没想到nullptr和NULL得区别,大了去了

::initializer_list型别的形参 //那么 {} 会强烈优先选择带有这个形参的重载版本 class WidgetBB{ public: WidgetBB(int i...复制构造函数 // WidgetBB w6{w444};//大括号,调用的是带有 std::initializer_list型别形参的构造函数,w4的返回值被强制转成成 float,随后 float又被强制转成了...//如果的确想调用一个带有 std::initializer_list 型别形参的构造函数,并传入一个空的 std::initializer_list的话 //可以通过把空大括号对作为构造函数实参的方式实现这个目的...,得到一个包含 2 个元素的 std::vector doSomeWorkstd::vector>(10,20); 测试端 int main() { cout的 std::tuple型别的各个阈时,假设为一个社交网站准备一个元组来持有名字,电子邮件和声望值 using UserInfo = std::tuplestd::string,

1.8K30
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【重学 C++】06 | C++该不该使用 explicit

    , std::string a, int p) :title_(t), author_(a), pages_(p) {}};改完Book的定义后,直接编译代码,发现是可以编译通过的,但再看下代码输出:call...所以会编译失败。单入参std::initializer_list的构造函数std::initializer_list 是 C++11 中引入的一种特殊类型,用于简化在初始化对象时传递初始化列表的过程。...() {MyClass obj = {1, 2, 3, 4, 5}; // 使用初始化列表语法进行隐式转换}对于带有std::initializer_list类型参数的构造函数,也不推荐使用explicit...因为使用std::initializer_list作为构造函数的入参,就是为了方便初始化对象。...对于带有单入参std::initializer_list的构造函数,也不推荐使用explicit,以方便使用初始化列表语法进行隐式转换。同类型的扩展类,为了避免差异化,隐式转换会更合适。

    25000

    【C++之STL】一文学会使用 string

    后者是返回 string 对象可以达到的最大长度,这是由已知的系统或库实现限制推断出的字符串可以达到的最大潜在长度,但不能保证对象能够达到该长度,在达到该长度之前,它仍然可能无法在任何时候分配存储。...这个接口的意义是减少扩容带来的损耗,编译器在创建一个 string 实例化对象时,并不知道它最终会存储多少数据,因此使用过程中不可避免地需要扩容,而我们知道扩容是有效率损耗的(如果原来的地址后面的空间不足...但是这个接口是非强制性的,C++标准只规定这个接口调用后,对象的容量不低于其大小就可以了,编译器可以在此基础上任意优化。 empty() (重要) 返回对象是否为空(即其长度是否为 0)。...用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导...getline() (重要) 我们时常会需要输入一个带有空格的字符串,在C语言中,带有空格的字符串只能通过循环调用getchar()来实现,但在 C++ 中提供了getline函数来解决这一问题。

    19510

    【C++11】统一的 {} 列表初始化

    ,却无法使用这样的初始化,比如: vector v{1,2,3,4,5}; ​ 在 c++98 中无法通过编译,导致每次定义 vector 时,都需要先把 vector 定义出来,然后使用循环对其赋初始值...可以通过编译,从long double到float截断 return 0; } ​ 在 C++ 中,将一个 const int 类型的值赋给 char 类型的变量时,编译器会发生一种叫做 整数类型收缩...整数类型收缩发生在以下场景中:将一个整数类型的值赋给另一个较小的整数类型的变量时,编译器会将原来类型的值的高位截断,然后赋给目标类型的变量。这个过程中,可能会导致信息的丢失或不可预期的行为。...引入 std::initializer_list 官方文档 ​ 我们来看看上面出现的一个问题: vector v1{1,2,3,4,5}; ​ 这么仔细一想,这里的 {1,2,3,4,5} 是怎么构造给...).name() << endl; return 0; } // 运行结果 class std::initializer_list ​ 那么我们如何在模拟实现 vector、list 等容器的时候增加

    8200

    C++一行代码实现任意系统函数Hook!

    std::is_same_v){ return RET{}; } }}; 这里即使wcscmp_compiletime函数可以实现编译期的字符串比较也不能实现编译期的结果计算...,测试是这样原因,应该是编译器还是将funcName当做一个外部符号有关?...std::is_same_v){ return RET{}; } }}; 四、从汇编角度看生成的一个API案例 简化后的测试代码如下:...推荐阅读 深入理解Linux的TCP三次握手! 如何用Go实现一个异步网络库? 如何优雅地实现C++编译期多态? C++异步:libunifex的scheduler实现!...温馨提示:因公众号平台更改了推送规则,公众号推送的文章文末需要点一下“赞”和“在看”,新的文章才会第一时间出现在你的订阅列表里噢~

    1.3K20

    C++ 特性使用建议

    2.右值引用 建议:只在定义移动构造函数与移动赋值操作时使用右值引用,区分std::move与std::forward的作用。...但是缺省参数函数调用的代码难以呈现所有参数,开发者只能通过查看函数申明或定义确定如何使用API,当缺省参数不适用于新代码时可能导致重大问题。...比如进行工厂类测试时,用来验证一个新建对象是否为期望的动态类型。RTTI 对于管理对象和派生对象的关系也很有用。 缺点: (1)在运行时判断类型通常意味着设计问题。...千万别用宏进行条件编译,会令测试更加痛苦 ,当然使用条件宏防止头文件重复包含是个特例。...,哪怕没有接收 std::initializer_list 的构造函数。

    1.7K20

    性能大杀器:c++中的copy elision

    ,输出: Default ctor Default ctor PS:本文中所使用的编译器及版本为gcc 11.4.0,如果未做显式说明,在编译过程中都加上-std=c++11选项。...好了,仍然是上面的代码,如果编译选项变成-std=c++11 -fno-elide-constructors,输出试试,看看会是什么结果~~ emm,在本地尝试编译并运行了下: Default ctor...,此处假设为temp2 Copy ctor // 通过调用拷贝构造函数,将temp2值赋值给o2 在上一节中,我们提到过,可以通过使用移动构造的方式来避免拷贝,为了测试该功能,尝试在Obj类中新增一个移动构造函数...这意味着,当函数返回一个自动对象时,编译器可以优化掉不必要的拷贝或移动操作,直接将自动对象构造到函数调用的返回对象中,以提高效率。这种优化在 C++ 标准中被明确规定,以支持更高效的代码生成。...标准的这一规定,使得原本不支持拷贝的对象,作为函数返回值时,也成了可能。

    16810

    C++17中新特性

    // c++11 auto x3{ 1, 2 }; // std::initializer_list auto x4 = { 3 }; // decltype(x4) is std::initializer_list... auto x5{ 3 }; // std::initializer_list 这三种方式初始化的变量,最终类型推导的结果都是 std::initializer_list<int...这是因为 当用于auto声明变量的表达式是{}括起来的,推导的型别就会变成 std::initializer_list。...,值不存在时则抛出 std::bad_optional_access 异常 value_or() // 值存在时返回值,不存在时返回默认值 3. std::any 一个类型安全的可以保存任何值的容器...string_view 本身没有申请额外的内存来存储原始字符串的data, 仅仅保存了原始字符串地址和长度等信息。 在很多情况下,我们只是临时处理字符串,本不需要对原始字符串的一份拷贝。

    4.9K30

    《Effective Modern C++》读书笔记

    ,收缩转换); 用{}替代(),可以避免A a()被编译器解析(parsed)成函数声明的问题; 缺点: 和auto结合得不友好,auto遇到{},auto推导成了std::initializer_list...,这不是所期望的; 当类的多个构造函数里,有一个是用std::initializer_list时,要注意其他构造函数不能用{}语法; 当类有类型转换函数时,第二个缺点会变得更严重:复制构造函数可能不会被调用...; 当存在std::initializer_list构造函数时,即使构造代码不正确,编译器也不会转而使用其他构造函数来构造(即使其他构造函数更加match),而是报错。...(一种例外情况是当{...}里的元素不能被转换成std::initializer_list的T时,编译器才会转而使用其他构造函数); 编写类构造函数的最佳实践 当你要给自定义的类加上std::initializer_list...从第二点可以反推,如果一个函数不是constexpr,那么即使你传递给它的参数都是编译时期已知的,这个函数也不一定就会在编译时期执行。 具体怎么玩?

    1.8K20

    【c++11】列表初始化与声明

    它常用于用户自定义的类或函数,使其可以接受固定数量的初始化元素。 1. 定义与特点 std::initializer_list 的定义位于头文件 initializer_list> 中。...它的主要特点包括: 表示一组常量值的不可变数组(只读的顺序容器)。 提供对数组元素的访问,但不能修改其中的值。 由编译器隐式生成,用户无需直接构造 initializer_list 对象。 2....size; } // 获取元素数量 constexpr size_t size() const noexcept { return _size; } private: // 构造时由编译器自动设置...编译器负责管理其生命周期,因此程序员不需要关心内存管理。 5. 注意事项 不可修改内容:std::initializer_list 中的内容是常量,不能被修改。...,尤其是在使用模板时 2.1 auto 在C++98中auto是一个存储类型的说明符,表明变量是局部自动存储类型,但是局部域中定义局部的变量默认就是自动存储类型,所以auto就没什么价值了。

    13510

    《Effective Modren C++》 进阶学习(上)

    那完美的标准是什么,我想不同的设计师都会有自己的一套标准。而在实际编码中,如何将个人的标准愈发完善,愈发得到同事的认可,一定需要不断积累。...编译时,通过编译器诊断信息 通过编译器出错时提供的错误消息也可以查看推导结果。 运行时,通过C++提供的接口typeid或者Boost.TypeIndex。 但是编译器的打印的类型并不是完全可靠的!...编译错误!要求变窄转换 只有当传入的参数在编译器上无法转换成std::initializer_list中的T类型,才会匹配普通的构造函数。...当使用{}初始化无参数时,会优先匹配默认构造函数,如果要匹配std::initializer_list构造函数,需要传入{}。 8....使用constexpr可以在编译时对常量表达式进行类型检查和错误检查。如果在常量表达式中使用了不允许的操作或无效的值,编译器会在编译时发出错误或警告,帮助我们及早发现并修复问题。 16.

    20320

    Effective Modern C++翻译(3)-条款2:明白auto类型推导

    f 在f的函数调用中,编译器使用expr来推导T和ParamType的类型。...,x5的类型需要被推导出来,另外因为auto是用大括号的初始化式初始化的,x5的类型必须被推导为std::initializer_list,但是std::initializer_list是一个模板,所以实例化模板...std::initializer_list模板的类型,而模板类型推导面对大括号的初始化式(braced initializer)时,代码将不会通过(这是由于完美转发perfect forwarding的结果...std::initializer_list类型的变量,但他们的本意却是想声明一个其他类型的变量。...auto用于C++14的lambda(产生一个通用的lambda(generic lambda))的参数类型说明符时, std::vector v; auto resetV = [&v](const

    714100

    【Cocos2d-x游戏开发】细数Cocos2d-x开发中那些常用的C++11知识

    使用std::initializer_list需要先include initializer_list>头文件*/ //函数使用初始化列表 void func(std::initializer_list...使用std::initializer_list需要先include initializer_list>头文件*/ //STL标准容器使用初始化列表 vector s = {"hello...","C++","11"};   可以看到在引入了std::initializer_list特性之后,初始化变量的工作简洁了许多,非常方便。  ...使用std::function可以存储Lambda函数,比如可以用function来存储func0,用function来存储func1,带有参数的函数可以直接在()内输入参数类型...在编译时,编译器会为标记为override的虚函数检查其父类是否有该虚函数: class B{ public: virtual void virtuaalFunc(int); }; class

    48330

    CC++开发基础——可变参数与可变参数模板

    2.如果可变参数的参数类型不同,可以使用可变参数模板。 C语言中,在定义可变参数函数时,使用省略号"..."表示参数是可变的。...initializer_list中的参数可以使用迭代器来访问。 initializer_list实例中传入参数时需要使用{}把多个参数括起来。...运行结果: 1 2 3.14 test I am empty. 4.sizeof...运算符 由于带有"typename T"参数的可变参数的模板函数,总是需要再定义一个同名的模板函数或者普通函数来搭配使用...运算符来保证,在不重复定义同名函数的情况下让递归退出。 "sizeof..."运算符可以判断参数包中的元素数量。 退出递归的方式: 判断当参数包的元素个数为零时,退出函数调用。...为了解决以上问题,C++17标准中引入了编译期if条件判断的表达式"if constexpr"。

    71450

    C++特性使用建议

    2.右值引用 建议: 只在定义移动构造函数与移动赋值操作时使用右值引用,区分std::move与std::forward的作用。...但是缺省参数函数调用的代码难以呈现所有参数,开发者只能通过查看函数申明或定义确定如何使用API,当缺省参数不适用于新代码时可能导致重大问题。...比如进行工厂类测试时,用来验证一个新建对象是否为期望的动态类型。RTTI 对于管理对象和派生对象的关系也很有用。 缺点: (1)在运行时判断类型通常意味着设计问题。...用宏进行条件编译… 这个,千万别这么做,会令测试更加痛苦 (#define 防止头文件重包含当然是个特例)。...,哪怕没有接收 std::initializer_list 的构造函数。

    1.9K30

    c++17好用的新特性总结

    auto x5{ 3 }; // std::initializer_list 这三种方式初始化的变量,最终类型推导的结果都是 std::initializer_list ,...std::endl; }(); } 在clang环境下,可以在lambda表达式捕获时显式引入一个引用变量通过编译: for(const auto& [key, value]: map){...c++17 std::pair p3{3.14, "pi"s}; if constexpr if constexpr语句是编译期的if判断语句,在C++17以前做编译期的条件判断往往通过复杂SFINAE...mutex_; unsigned int value_ = 0; }; std::string_view std::string_view顾名思义是字符串的“视图”,类成员变量包含两个部分:字符串指针和字符串长度...std::any应当很少是程序员的第一选择,在已知类型的情况下,std::optional, std::variant和继承都是比它更高效、更合理的选择。

    3.4K10

    列表初始化:轻量级对象initializer_list

    例如,int x = {2.5};会编译错误,防止精度丢失。...但是,编译器会进行优化,直接构造d1,避免了拷贝构造。 const Date& d2 = {2024, 7, 25};:引用一个临时的Date对象,该对象由列表初始化创建。...背景 在C++98中,初始化数组和聚合类型(如结构体)可以使用大括号{},但对于容器和自定义类的初始化,尤其是当需要传入多个参数时,显得不够方便。...std::initializer_list的原理 std::initializer_list是C++11标准库中的一个模板类,用于表示由大括号{}括起来的一系列元素。...调用函数时传入列表:在调用printValues时,直接传入一个初始化列表{10, 20, 30, 40, 50},也可以作为构造函数或拷贝构造函数等的实参进行传入。

    28310

    再探函数

    initializer_list形参 initializer_list是一种标准库类型,用于表示某种特定类型的值的数组 initializer_list也是一种模板类型 支持size(),begin(...),end()等操作 向initializer_list形参中传递一个值的序列,则必须把序列放在花括号中 #include using namespace std; void print..._1(initializer_list str) { //遍历实参表列,使用initializer_list对象的成员begin和end进行遍历 cout的是内置类型,则花括号包围的列表最多包含一个值,而且该值所占空间不应该大于目标类型的空间 如果函数返回的是类类型,由类本身定义初始值如何使用 #include #include...func:存放当前调试函数的名字 FILE:存放文件名的字符串字面值常量 LINE:存放文件当前行号的整型字面值 TIME:存放文件编译时间的字符串字面值常量 DATE:存放文件编译日期的字符串字面值常量

    37910
    领券