c++小知识点,noexcept,explicit,vector.emplace_back特点
1. noexcept
noexcept 是 C++ 中的一个关键字,用于指示一个函数或者表达式是否会抛出异常。它有两个主要的用途:
-  在函数声明中表示不抛出异常: myFunction() noexcept { // 函数体 }在这个例子中, noexcept表明myFunction不会抛出异常。如果在函数声明中使用了noexcept,而在实际的函数调用中发生了异常,程序会调用std::terminate来终止程序。
-  在运行时检查是否抛出异常: try { // 一些可能抛出异常的代码 } catch (...) { // 异常处理代码 }如果你在 try块内使用了noexcept的函数,而在这个函数中抛出了异常,那么程序会立即调用std::terminate,而不是执行catch块内的代码。这有助于在编译时和运行时都更好地处理异常。
noexcept 对于移动构造函数和移动赋值运算符的使用也很常见,例如:
class MyClass {
public:
    // 移动构造函数,标记为 noexcept
    MyClass(MyClass&& other) noexcept {
        // 实现移动构造逻辑
    }
    // 移动赋值运算符,标记为 noexcept
    MyClass& operator=(MyClass&& other) noexcept {
        // 实现移动赋值逻辑
        return *this;
    }
};
这有助于优化容器和算法的性能,因为容器和算法可以利用 noexcept 的信息来进行更有效的实现。
2. explicit
explicit 是 C++ 中的一个关键字,通常用于声明一个类的单参数构造函数,以防止编译器进行隐式类型转换。使用 explicit 关键字可以明确指定只能使用显式构造调用,而禁止隐式转换。
考虑下面的例子:
class MyClass {
public:
    // 隐式转换构造函数
    MyClass(int x) {
        // 构造逻辑
    }
};
int main() {
    MyClass obj = 42;  // 隐式转换
    return 0;
}
在这个例子中,MyClass 有一个接受整数参数的构造函数,这可能导致隐式类型转换。为了防止这种情况,可以使用 explicit:
class MyClass {
public:
    // 显式构造函数
    explicit MyClass(int x) {
        // 构造逻辑
    }
};
int main() {
    MyClass obj = 42;  // 编译错误,因为构造函数是显式的
    MyClass obj2(42);  // 正确,使用显式构造
    return 0;
}
通过在构造函数前加上 explicit,我们告诉编译器只能使用显式构造函数调用,这样就避免了隐式类型转换。这可以帮助防止一些潜在的错误和提高代码的清晰度,因为它强调了在哪里发生了类型转换。
3.vector.emplace_back()
readers.emplace_back(readOperation, i); 这一句中,emplace_back 用于在 readers 向量的末尾构造一个 std::thread 对象。在这个过程中,实际上调用了 std::thread 的构造函数,它是通过可变参数模板来实现的。
在这种情况下,std::thread 的构造函数是通过以下的模板构造函数之一来完成的:
template <class F, class... Args>
explicit thread(F&& f, Args&&... args);
其中,F 是可调用对象(函数指针、函数对象等),而 Args 是可调用对象 f 的参数。
具体到你的例子,emplace_back 会根据参数类型来实例化 std::thread 的构造函数。假设 readOperation 是一个函数,i 是一个整数,那么构造函数会被实例化为:
std::thread::thread(void(*f)(int), int);
这个构造函数接受一个函数指针(指向 void readOperation(int) 类型的函数)和一个整数作为参数。std::thread 的构造函数会将 readOperation 函数和 i 参数传递给新创建的线程对象,以便线程在执行时调用这个函数,并传递参数 i。
这样,std::thread 的构造函数会在内部启动一个新的线程,并执行 readOperation 函数,将 i 作为参数传递给它。这就是这个构造函数的基本工作原理。
emplace_back 相对于 push_back 的优点主要在于避免了额外的拷贝或移动操作,特别是对于容器中存储的复杂对象或者用户自定义类型而言。以下是 emplace_back 的一些优点:
-  避免了多余的拷贝或移动: - emplace_back允许在容器中直接构造对象,而不是先创建一个临时对象再将其拷贝或移动到容器中。这在性能上可以带来显著的优势,尤其是对于大型、复杂的对象。
 
-  减少了额外的内存分配和释放: - 对于容器中的元素类型,emplace_back可以直接在容器的内存中构造对象,而不需要为临时对象分配额外的内存。这有助于减少内存管理的开销。
 
- 对于容器中的元素类型,
-  支持完美转发: - emplace_back使用了完美转发,允许将参数直接传递给元素类型的构造函数,而不需要显式地创建一个对象。这提供了更大的灵活性,特别是当元素类型的构造函数有多个参数时。
 
-  对于不可拷贝、不可移动类型的支持: - 对于某些类型,可能没有合适的拷贝构造函数或移动构造函数。在这种情况下,使用 emplace_back可能是唯一的选择,因为它允许直接在容器中构造对象。
 
- 对于某些类型,可能没有合适的拷贝构造函数或移动构造函数。在这种情况下,使用 
-  更好的性能: - 在某些情况下,使用 emplace_back可以显著提高性能,尤其是当插入大量元素时。这是因为它避免了不必要的对象创建和拷贝/移动操作。
 
- 在某些情况下,使用 
综上所述,emplace_back 提供了一种更加灵活和高效的元素插入方式,特别适用于处理复杂对象或者用户自定义类型的容器。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!