自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(912)
  • 资源 (2)
  • 收藏
  • 关注

原创 进程通信(11)System V共享内存区

具体来说,它会更新 shmid_ds 结构中的 shm_perm.uid、shm_perm.gid 和 shm_perm.mode 成员,这些值来自于 buf 指向的结构体。创建或获取共享内存标识符:使用shmget系统调用,根据给定的关键字(key)、大小和标志创建一个新的共享内存段或获取一个已存在的共享内存段的标识符(ID)。将共享内存段附加到进程地址空间:使用shmat系统调用将由shmget返回的共享内存段ID所标识的共享内存段附加到调用进程的地址空间。它只是解除了该进程对共享内存段的访问。

2024-12-30 23:50:21 608

原创 进程通信(10):Posix 共享内存区

POSIX.1提供了两种主要的方法来实现这一目标:1. 内存映射文件描述符获取:通过open函数打开一个文件,并获得其文件描述符。映射过程:使用mmap函数将该文件映射到当前进程的地址空间。适用场景:不仅可以用于父子进程间的共享,还可以用于无亲缘关系的进程之间。只要所有需要访问该共享内存区的进程都能够打开同一个文件,它们就可以共享由该文件映射而来的内存区域。2. 共享内存区对象描述符获取:通过shm_open函数打开或创建一个Posix IPC名字(可能是文件系统中的路径名),并返回一个描述符。

2024-12-30 22:47:43 798

原创 进程通信(9):记录上锁

而本章讨论的是另一种类型的读写锁,它允许有亲缘关系或无亲缘关系的进程之间共享文件的读与写。这种类型的锁是基于文件描述符并通过函数fcntl实现的,其维护是在内核层面完成的,并且是以进程ID来标识锁的所有者。内核不会阻止一个进程写入已被另一个进程读锁定的文件,也不会阻止一个进程读取已被另一个进程写锁定的文件。在这种情况下,所有涉及的进程都遵循约定,尊重其他进程设置的锁。例如,在网络编程中,守护程序通常都是协作的,它们访问共享资源如序列号文件,并且都在系统管理员的控制之下。解锁时,unlink掉锁文件。

2024-12-30 21:21:59 710

原创 进程通信(8)读写锁

读写锁是一种同步原语,用于管理对共享资源或临界区的访问,允许多个线程同时读取数据(共享锁),但当有线程需要写入数据时(独占锁),则要求排他性的访问,即不允许其他任何线程(无论是读还是写)同时访问该数据。这种机制在读操作远多于写操作的应用场景中,能显著提高并发性能。读写锁的工作原理(1)共享锁(读锁):当没有线程持有写锁时,任意数量的线程可以同时持有读锁。持有读锁的线程只能进行读操作,不能修改共享资源。

2024-12-30 20:34:45 1165

原创 C++并发编程实战:第4章 同步并发操作

std::future和std::shared_future通常与std::async、std::promise等一起使用来创建异步任务和管理其结果。如果 std::promise 或 std::packaged_task 在没有调用 set_value() 或 set_exception() 的情况下被销毁,那么与之关联的 std::future 会接收到一个 std::future_error 异常,错误码为std::future_errc::broken_promise。最优的选择是利用条件变量。

2024-12-27 17:46:12 1021

原创 C++并发编程实战 第三章 线程间共享数据

add_to_list() 和 list_contains() 函数使用 std::lock_guard 来确保对 some_list 的访问是互斥的,即一个线程在修改列表时,其他线程不能读取或修改该列表。除了上述特性外,std::unique_lock 还支持锁所有权的转移,这意味着你可以将一个 std::unique_lock 持有的锁转移给另一个 std::unique_lock 实例。因为两个线程可能尝试在相同的一对实例之间交换数据,但选择了相反的锁定顺序,从而导致死锁。

2024-12-26 10:16:25 547

原创 C++并发编程实战(二):线程管理

一旦线程完成并且join()返回后,std::thread对象将不再关联任何线程,因此不能再次调用join()。如果std::thread对象在其析构之前没有被join()或detach(),那么析构函数会调用std::terminate()终止程序。因此,必须确保在线程对象销毁之前,要么join()要么detach()。如果std::thread对象没有关联任何执行线程(例如,它已经被join()或detach()),则get_id()将返回默认构造的std::thread::id值,表示“没有线程”。

2024-12-25 11:47:21 793

原创 Modern Effective C++ 条款四十二:考虑使用置入代替插入

考虑一个例子,如果尝试将 nullptr 添加到 std::vector<std::regex> 中,emplace_back 会成功编译,而 push_back 则不会,因为 std::regex 的构造函数是 explicit 的,不允许从 nullptr 进行隐式转换。这种场景不容易描述,因为依赖于传递的实参的类型、使用的容器、置入或插入到容器中的位置、容器中类型的构造函数的异常安全性,和对于禁止重复值的容器(即。时,没有理由期望置入比插入运行的更快,因为不需要创建临时对象来满足插入的接口。

2024-12-10 20:18:09 726

原创 Modern Effective C++ 条款四十一:对于移动成本低且总是被拷贝的可拷贝形参,考虑按值传递

对于特殊的场景,可拷贝且移动开销小的类型,传递给总是会拷贝他们的一个函数,并且切片也不需要考虑,这时,按值传递就提供了一种简单的实现方式,效率接近传递引用的函数,但是避免了传引用方案的缺点。然而,由于移动操作通常比拷贝更轻量级,特别是对于大型对象或者资源管理类(如std::string),这种额外的开销通常是可接受的。(3)高效利用现代C++特性:得益于C++11的移动语义,当传入的是右值时,newName会通过移动构造而不是复制构造初始化,从而提高了性能。为了提高效率,应该拷贝左值,移动右值。

2024-12-10 19:42:22 899

原创 Modern Effective C++ 条款四十:对于并发使用std::atomic,对于特殊内存使用volatile

但是在编译器拿到看起来合理的代码,执行了模板实例化,内联和一系列重排序优化之后,结果会出现冗余访问和无用存储,所以编译器需要摆脱这样的情况并不少见。由于auto推导出的y是一个普通的int类型,它不受volatile的影响,因此对y的操作可以被优化。对象被构建,在其上的操作表现得像操作是在互斥锁保护的关键区内,但是通常这些操作是使用特定的机器指令实现,这比锁的实现更高效。对象,这也是默认的和唯一的一致性模型。那些不那么相同,但是如果我们暂时忽略它,只关注编译器执行的操作,则概念上可以说,编译器看到这个,

2024-12-10 10:48:47 751

原创 Modern Effective C++ 条款三十九:对于一次性事件通信考虑使用void的futures

虽然 std::promise 和 std::future 提供了一种简洁且有效的线程间通信方式,并解决了条件变量和标志位设计中的某些问题,但它们也有自己的局限性和适用范围。即使检测任务和反应任务之间没有共享数据的竞争,我们仍然需要互斥锁来防止所谓的“竞态条件”,即检测任务可能在反应任务检查条件之前改变了条件,但又在反应任务开始等待之前再次改变条件。这种情况下,反应任务可能会错过通知。使用共享的布尔型 flag 进行线程间通信的方法确实避免了条件变量设计中的一些复杂性,如互斥锁的需要和虚假唤醒的问题。

2024-12-09 21:53:22 747

原创 Modern Effective C++ 条款三十八:关注不同线程句柄的析构行为

这样的设计使得即使原始的std::promise和第一个std::future被销毁后,其他std::shared_future实例仍然能够访问结果,只要还有至少一个std::future或std::shared_future存在,共享状态就会保持有效,确保只可移动类型的结果可以被正确处理,因为移动操作不会影响共享状态中的实际数据。(1)关联到由 std::async 创建的共享状态:意味该 future 是通过调用 std::async 来创建的,而 std::async 通常用于启动异步任务。

2024-12-08 10:58:42 644

原创 Modern Effective C++ 条款三十七:使std::thread在所有路径最后都不可结合

调用 detach() 后,std::thread 对象不再跟踪这个线程的状态,且不能再次通过这个对象来管理和访问该线程。已调用 detach():当你调用 detach() 方法时,它将分离 std::thread 和底层线程之间的关系,使得线程可以独立运行,而 std::thread 对象不再跟踪这个线程的状态。当一个处于可结合状态的std::thread对象被销毁时(即其析构函数被调用),如果这个线程还没有被join或detach,那么程序将调用std::terminate,导致程序异常终止。

2024-12-07 23:16:41 846

原创 Modern Effective C++条款三十六:如果有异步的必要请指定std::launch::async

如果任务是在不同的线程上执行的,那么它可能会访问到该线程的thread_local 变量的不同实例,这可能导致意外的行为或错误。为了避免这些问题,如果你的任务逻辑中涉及 thread_local 变量,最好显式指定 std::launch::async 策略来确保任务始终在一个新的线程上异步执行,或者重构你的代码以避免对 thread_local 变量的依赖。(4) 影响 thread_local 变量:因为不知道哪个线程会执行任务,所以也就不知道哪个线程的 thread_local 变量会被访问。

2024-12-05 17:52:03 641

原创 Modern Effective C++条款三十五:优先考虑基于任务的编程而非基于线程的编程

它可以代表一个正在运行的软件线程,也可以是未关联任何线程的空句柄(如默认构造的std::thread)。访问底层线程API:当需要使用非常基础的线程功能或操作系统级别的特性(如线程优先级、亲和性等),std::thread提供的native_handle成员函数可以直接访问底层API,而std::future不具备这种能力。(1)线程限额:操作系统能够支持的线程数量是有限的。实现特殊线程技术:当需要使用C++并发API之外的技术(如未被支持的平台上的线程池)时,std::thread提供了更大的灵活性。

2024-12-05 17:25:11 877

原创 Modern Effective C++条款三十四:考虑lambda而非std::bind

当使用steady_clock::now() + 1h作为std::bind的一个参数时,这个表达式是在std::bind被调用的那一刻就被计算(即立即求值),而不是在最终调用setAlarm时计算。当执行 std::bind(&std::chrono::steady_clock::now)时,实际上在创建一个函数对象,不带任何参数,并且当这个函数对象被调用时,会调用 steady_clock::now() 来获取当前的时间点。在C++11中,std::bind可用于模拟移动捕获和创建多态函数对象。

2024-12-05 16:27:20 894

原创 Modern Effective C++ 条款32&33:使用初始化捕获来移动对象到闭包中 / 对auto&&形参使用decltype以std::forward它们

C++11闭包捕获机制仅支持按值或按引用捕获变量,这使得对于只能移动的对象(如std::unique_ptr或std::future)的处理变得困难。此外,对于复制开销高的对象,C++11无法直接实现更高效的移动语义来代替复制。C++14引入了初始化捕获(也称为通用lambda捕获),使得开发者可以将表达式的结果直接作为闭包的数据成员进行初始化,并且允许使用std::move将不可复制的对象移动到闭包中。这种新形式的捕获为开发者提供了更大的灵活性和效率。

2024-12-04 17:17:05 550

原创 Modern Effective C++ 条款三十一:避免使用默认捕获模式

因此,lambda表达式访问的局部变量在整个操作期间都是有效的,不存在悬空引用的风险。这种情况下,默认按引用捕获模式([&])是安全的,因为此时lambda表达式的生命周期与父函数中局部变量的生命周期是一致的。比如,如果一个变量是在lambda创建后很快就会销毁的局部变量,那么按值捕获可能是更好的选择,以确保lambda内部持有该变量的一个独立副本。默认按引用捕获模式可能会带来悬空引用的问题,而默认按值捕获模式也没有解决这个问题,还会让你以为你的闭包是独立的(事实上也不是独立的)。

2024-12-04 16:08:00 763

原创 Modern Effective C++ 条款二十九&三十:移动语义和完美转发失败的情况

告诉编译器某个实体(变量,函数,类等)的名称和类型,不为其分配存储空间。不仅告诉编译器实体的名称和类型,还为其分配存储空间,并可能提供初始化值或实现。static const 整型数据成员的特殊情况。对于static const整型数据成员,可以在类内部进行初始化,但这实际上是声明的一部分。编译器会将这个常量的值传播到所有使用它的地方,从而不需要为它分配实际的存储空间。

2024-12-03 11:29:21 1281

原创 Modern Effective C++ 条款二十八:理解引用折叠

static_cast<Widget&&>(param) 将 param 转换为右值引用,即使 param在std::forward 内部是一个左值引用,但通过 static_cast<Widget&&>(param),它被转换为右值引用。但是编译器没有报错。存在两种类型的引用(左值和右值),所以有四种可能的引用组合(左值的左值,左值的右值,右值的右值,右值的左值)。T 是一个模板参数,std::remove_reference<T>::type 用来去除 T 中可能存在的引用类型,从而得到原始类型。

2024-12-02 15:45:00 907

原创 Modern Effective C++ 条款二十七:熟悉通用引用重载的替代方法

第一个构造函数接受std::string类型的参数,并使用std::move来转移所有权,允许编译器进行潜在的优化。std::is_integral<std::remove_reference_t<T>>::value 确保T不是整型。这个类型参数通常是一个std::true_type或std::false_type,是标准库提供的类型,用于表示布尔值。使用 std::is_base_of 和 std::is_integral,std::is_base_of 用于检查类型是否是 Person 或其派生类。

2024-12-02 13:53:14 721

原创 Modern Effective C++ 条款二十六:避免在通用引用上重载

如果用户尝试用非int类型的整数(例如short, long, std::size_t等)来创建Person对象,编译器会优先选择模板化的完美转发构造函数,而不是预期的int构造函数。因此,传递这些整数类型会导致调用模板构造函数,进而可能导致编译错误,因为std::string没有接受这些整数类型的构造函数。当调用logAndAdd并传入short类型的索引时,编译器会优先选择T&&版本的logAndAdd,因为short可以直接绑定到T&&上,而不需要转换。标签分派可以帮助编译器选择正确的构造函数实现。

2024-12-02 10:17:15 973

原创 Modern Effective C++ 条款二十五:对右值引用使用std::move,对通用引用使用std::forward

对于右值引用,同但在某些情况下,应该使用std::move_if_noexcept而不是std::move,以确保在移动构造函数不可用或抛出异常时仍能安全地进行拷贝。有一个形参,因此需要两种重载实现,但是对于有更多形参的函数,每个都可能是左值或右值,重载函数的数量几何式增长:n个参数的话,就要实现2^n种重载。当你有一个按值返回的函数,其中返回值绑定到一个右值引用上时,应该使用std::move来确保执行移动操作,从而提高效率。在按值返回的函数中使用std::move和std::forward。

2024-11-30 12:22:27 1028

原创 Modern Effective C++ 条款二十四:区分通用引用与右值引用

Args&&... args 是一个通用引用,因为形式是 type&&,并且 Args 的类型会在每次调用时被推导。初始值决定引用类型:通用引用的初始值决定了它是左值引用还是右值引用。MyTemplateType 可以是任何类型,param 是一个通用引用,因为其形式是 type&&,并且 MyTemplateType 的类型会在调用时被推导。auto&& 声明的变量是通用引用,因为会发生类型推导,并且形式是 type&&。当 T&& 用在一个有类型推导的地方时,它被称为通用引用或转发引用。

2024-11-30 11:39:25 682

原创 Modern Effective C++ 条款二十三:理解std::move和std::forward

在模板函数 logAndProcess 中,如果不使用 std::forward<T>(param) 而直接使用 param,那么无论传递给 logAndProcess 的是左值还是右值,param 都会被视为左值。std::forward 是一个有条件的转换,只有当传递给它的参数是右值时,它才会将参数转换为右值引用。使用 std::forward 在模板中转发参数时,保持参数的原始值类别。(2)std::move 不保证移动:std::move 只是将对象转换为右值引用,但并不保证实际的移动会发生。

2024-11-30 10:50:19 1006

原创 Modern Effective C++ 条款二十二:当使用Pimpl惯用法,请在实现文件中定义特殊成员函数

使用std::shared_ptr的差异:如果使用std::shared_ptr而不是std::unique_ptr,则不需要在头文件中声明析构函数,因为std::shared_ptr的删除器类型不是智能指针的一部分,因此它可以在不完整类型上工作。如果使用std::unique_ptr,需要显式地声明析构函数并在实现文件中定义它,以确保在销毁std::unique_ptr前Impl已被定义。由于std::unique_ptr的删除器类型是其一部分,编译器需要知道完整的类型信息来生成正确的删除代码。

2024-11-28 23:27:49 813

原创 Modern Effective C++条款二十一:优先考虑使用std::make_unique和std::make_shared,而非直接使用new

如果computePriority()抛出异常,由于std::make_shared已经成功创建了std::shared_ptr,并且这个智能指针已经开始管理Widget对象,所以在异常处理过程中,std::shared_ptr的析构函数会被调用,从而释放Widget对象占用的内存。对于大型对象,如果使用std::make_shared,则对象的内存会在最后一个std::shared_ptr和最后一个std::weak_ptr都被销毁后才释放。如果需要指定自定义删除器,则必须直接使用new。

2024-11-28 19:37:10 800

原创 Modern Effective C++ 条款二十:当std::shared_ptr可能悬空时使用std::weak_ptr

如果缓存直接使用std::shared_ptr来存储对象,那么即使所有客户端都释放了它们的std::shared_ptr,缓存中的std::shared_ptr仍然会保持对象的存活,导致内存泄漏。效率比较:std::shared_ptr和std::weak_ptr在大多数实现中具有相同的大小,因为它们都存储了一个指向控制块的指针。赋值:将一个std::weak_ptr赋值给另一个std::weak_ptr时,源std::weak_ptr的弱引用计数减少1,目标std::weak_ptr的弱引用计数增加1。

2024-11-28 14:06:40 611

原创 Modern Effecive C++ 条款十九:对于共享资源使用std::shared_ptr

如果Widget对象已经被std::shared_ptr管理,那么将this传递给emplace_back会创建一个新的std::shared_ptr,这可能导致多重控制块问题(即多个std::shared_ptr管理同一个对象)。引用计数本身是存储在独立于所管理对象的内存块中的。(2)独占资源:如果不需要共享所有权,使用 std::unique_ptr 更合适,因为它具有接近原始指针的性能,并且可以从 std::unique_ptr 转换为 std::shared_ptr,反之则不行。

2024-11-27 21:53:19 499

原创 Modern Effective C++ 条款十八:对于独占资源使用std::unique_ptr

拷贝一个std::unique_ptr是不允许的,因为如果你能拷贝一个std::unique_ptr,会得到指向相同内容的两个std::unique_ptr,每个都认为自己拥有(并且应当最后销毁)资源,销毁时就会出现重复销毁。推荐使用 std::array、std::vector 或 std::string。数组管理:std::unique_ptr<T[]>用于管理动态分配的数组,但通常建议使用std::array、std::vector或std::string等容器代替原始数组。模板参数包:Ts&&…

2024-11-27 20:15:55 1354

原创 Modern Effective C++ 条款16&17:确保const成员函数线程安全条款&&特殊成员函数的生成

如果类没有任何用户定义的拷贝或移动操作,并且没有用户定义的析构函数,那么编译器可以自动生成移动构造函数和移动赋值运算符。默认情况下,这两个函数都会执行逐成员的移动操作,即调用每个成员的移动构造函数或移动赋值运算符。如果要让旧的C++98代码支持移动语义,需要使用C++11标准,并在类中添加相应的移动构造函数和移动赋值运算符。,它们是非虚的,除非相关函数是在派生类中的析构函数,派生类继承了有虚析构函数的基类。移动操作仅在需要的时候生成,如果生成了,就会对类的non-static数据成员执行逐成员的移动。

2024-11-27 19:23:18 698

原创 Modern Effective C++ item 15:尽可能的使用constexpr

当constexpr应用于函数时,表示函数可以在编译期执行,因为参数也是编译期常量。常量表达式构造函数拥有和常量表达式函数相同的退化特性,当它的实参不是常量表达式的时候,构造函数可以退化为普通构造函数,当然,这么做的前提是类型的声明对象不能为常量表达式值。正常工作,因为 10 是一个常量表达式,size(10) 可以在编译时计算其结果,并用于初始化 constexpr 变量 s_constexpr。constexpr还能定义一个常量表达式函数,即constexpr函数,常量表达式函数的返回值可以在编译。

2024-11-24 23:50:24 829

原创 Modern Effective C++ Item 14 如果函数不抛出异常请使用noexcept

例如,如果 std::vector 中的元素的析构函数抛出异常,可能会导致 std::vector 的析构函数无法正常完成,从而导致资源泄露。如果违反前置条件,函数的行为是未定义的。谨慎声明 noexcept,即使这些函数自然不会抛出异常,也应该谨慎声明为 noexcept,因为前置条件的检查可能需要抛出异常。对于严格契约的函数,即使它自然不会抛出异常,也应该谨慎声明 noexcept,因为前置条件的检查可能需要抛出异常。大多数函数是异常中立的,即它们自己不抛异常,但可能调用其他会抛异常的函数。

2024-11-23 16:16:01 565

原创 Modern Effective C++ item12&13 使用override&使用const_iterator

优先考虑 const_iterator而非 iterator:const_iterator 等价于指向常量的指针,不允许修改其指向的值。标准实践是能加上 const 就加上,防止意外修改数据。

2024-11-21 23:53:54 764

原创 Modern Effective C++ Item 11:优先考虑使用deleted函数而非使用未定义的私有声明

这种方法可以防止客户端调用这些函数,但如果在成员函数或友元函数中调用这些函数,会在链接时引发错误。C++11 使用 = delete 将这些函数标记为删除的函数。删除的函数不能以任何方式被调用,即使在成员函数或友元函数中调用也会在编译时失败。使用=delete可以禁止特定类型的函数调用,可以禁止特定类型的模板实例化,类内的模板函数特化,如果类内有一个模板函数,使用 = delete 可以在类外删除特定的模板实例。这是因为在类内不能给特化的成员模板函数指定不同的访问级别,而在类外删除这些函数不会有问题。

2024-11-21 13:30:31 779

原创 Modern Effective C++ Item 10:优先考虑限域enum而非未限域enum

C++已有的std::pair类型类似于一个二元组,可看作是std::tuple的一个特例,std::tuple也可看作是std::pair的泛化。std::pair的长度限制为2,而std::tuple的元素个数为0~任意个。std::tuple的一个常见用途是从一个函数返回多个值std::tuple中元素被紧密地存储的(位于连续的内存区域),而不是链式结构。可以将std::tuple看作一个“快速而随意”的数据结构,把它当作一个通用的结构体使用,但又不需要创建和获取结构体的特征,使得程序更加简洁。

2024-11-21 13:12:25 680

原创 Modern Effective C++item 9:优先考虑别名声明而非typedef

除了上面介绍的类型,type_traits 还有如 std::is_signed (检查类型是否有符号)、std::is_unsigned (检查类型是否无符号)、std::is_arithmetic ( 检查类型是否为算术类型(整数或浮点数))等基础核心类型。例如,std::is_integral 用于检查一个类型是否为整数类型,std::is_floating_point用于检查一个类型是否为浮点类型,std::is_base_of用于检查一个类型是否是另一个类型的基类等。

2024-11-21 12:23:28 475

原创 Modern Effective C++ Item 8:优先考虑nullptr而非0和NULL

在模板中,传递 0 或 NULL 会导致类型推导出整型,而不是指针类型。使用 nullptr 可以避免这些问题,因为 std::nullptr_t 可以隐式转换为任何指针类型,而不会导致类型错误。尽管 NULL 可以被定义为其他整型类型,但它的主要问题是它本质上仍然是一个整型,而不是指针类型。在 C++98 中,如果同时重载了指针和整型的函数,传递 0 或 NULL 会调用整型版本的函数,而不是指针版本的函数。0 的类型:在 C++ 中,字面值 0 默认是一个 int 类型,而不是指针类型。

2024-11-21 12:19:18 252

原创 Mordern Effective C++ Item 7:区别使用()和{}创建对象

(2)声明一个名为time_keeper的函数,该函数返回一个TimeKeeper类型的对象,并且有一个单一的(未命名的)参数,该参数的类型是一个(指向)不接受任何输入并返回Timer对象的函数。C++11使用统一初始化来整合这些混乱且不适于所有情景的初始化语法,统一初始化是指在任何涉及初始化的地方都使用单一的初始化语法。在变量声明的例子中,自C++11以来,首选的方法是使用统一(花括号)初始化。C++11对象初始化的语法有多种,初始化值要用圆括号()或者花括号{}括起来,或者放到等号"="的右边。

2024-11-19 22:01:32 583

原创 Modern Effective C++:Item 6 auto推导若非己愿,使用显式类型初始化惯用法

在运行时,std::vector<bool>::operator[]返回的std::vector<bool>::reference执行它支持的向bool的转型,在这个过程中指向std::vector<bool>的指针已经被解引用。对于d,类型并不是bool,而是一个vector<bool>中的一个内部类。其他的代理类则或多或少不可见,比如std::vector<bool>::reference就是不可见代理类的一个例子,还有它在std::bitset的胞弟std::bitset::reference。

2024-11-19 20:28:24 849

二叉树和链表.docx

二叉树和链表.docx

2024-03-19

eclipse连接hadoop

eclipse连接hadoop所需的配置文件和jar包。 使用说明: 参考博文:https://www.cnblogs.com/supiaopiao/p/7240308.html Tips: 上面网站中的第六步,打开eclipse的右上角有个田字格,选择Map/Reduce。 可能存在没有Map/Reduce字样的情况 解决方法: https://www.cnblogs.com/2016-zck/p/10298631.html

2022-05-16

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除