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进行投诉反馈,一经查实,立即删除!