目录
1、std::set
C++ 标准库中的一个关联容器,它存储唯一元素的集合,并且这些元素是自动排序的。每个元素只能出现一次,因为 std::set 内部使用的是平衡二叉查找树(通常是红黑树)来实现,这保证了其成员函数如插入、删除和查找等操作的时间复杂度为对数级别 O(log n)。
特点
- 唯一性:集合中的所有元素都是唯一的,不允许有重复值。
- 有序性:集合中的元素默认按照升序排列,但可以通过自定义比较器来改变排序规则。
- 双向迭代器:
std::set提供了双向迭代器,允许从任何位置向前或向后遍历集合。 - 动态大小:可以随时添加或删除元素,集合会自动调整大小。
常用方法
-
构造函数:
std::set<T> s;// 创建一个空的 setstd::set<T> s(begin, end);// 使用范围 [begin, end) 初始化 setstd::set<T> s(initializer_list);// 使用初始化列表创建 setstd::set<T> s(another_set);// 拷贝构造
-
插入元素:
s.insert(value);// 插入单个元素s.insert(begin, end);// 插入一个范围内的元素
-
删除元素:
s.erase(element);// 删除指定的元素s.erase(position);// 删除迭代器指向的位置s.erase(start, end);// 删除一个范围内的元素
-
查找元素:
s.find(element);// 查找指定元素,返回一个迭代器指向该元素,如果找不到则返回 end()
-
检查元素是否存在:
s.count(element);// 如果存在返回 1,否则返回 0
-
获取大小:
s.size();// 返回集合中元素的数量
-
清空集合:
s.clear();// 移除所有元素
-
迭代器:
s.begin();// 返回指向第一个元素的迭代器s.end();// 返回指向最后一个元素之后位置的迭代器
-
排序规则:
s.key_comp();// 返回一个比较对象,可用于比较两个键值s.value_comp();// 返回一个比较对象,可用于比较两个元素
#include <iostream>
#include <set>
int main() {
std::set<int> numbers;
// 插入元素
numbers.insert(10);
numbers.insert(30);
numbers.insert(20);
// 输出集合中的所有元素
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// 查找元素
if (numbers.find(20) != numbers.end()) {
std::cout << "找到了20" << std::endl;
}
// 删除元素
numbers.erase(20);
// 检查是否成功删除
if (numbers.find(20) == numbers.end()) {
std::cout << "20 已经被删除" << std::endl;
}
return 0;
}
注释:
for (const auto& num : numbers)
这是一个范围 for 循环(也称为基于范围的 for 循环),它用于遍历容器中的所有元素。这里的 numbers 是一个 std::set<int> 类型的容器。
-
const auto& num:-
auto: 编译器会根据numbers容器中的元素类型自动推断num的类型。因为numbers是一个std::set<int>,所以num的类型会被推断为int。 -
const: 表示num是一个常量引用,意味着你不能通过num修改numbers中的元素。 -
&: 表示num是一个引用,而不是一个新的变量。引用是原元素的别名,因此不会创建额外的副本,这在处理大型对象时可以提高性能。
-
-
numbers: 这是你遍历的容器,这里是一个std::set<int>。 -
2、std::ref
-
什么是
std::reference_wrapper?std::reference_wrapper是一个模板类,包装了一个引用。它提供了与原始引用类似的接口,但可以被传递和存储在容器中,而不会导致值的拷贝。为什么需要
std::ref? -
避免拷贝:对于大型对象或复杂数据结构,传递引用可以避免不必要的拷贝,提高性能。
-
传递引用:某些函数(如
std::thread构造函数)需要传递可复制的对象,而不仅仅是引用。std::ref可以将引用转换为可复制的对象。 -
基本用法
-
#include <iostream> #include <functional> #include <thread> void printValue(int& value) { std::cout << "Value: " << value << std::endl; } int main() { int x = 10; // 使用 std::ref 包装引用 std::reference_wrapper<int> ref_x = std::ref(x); // 传递引用给函数 printValue(ref_x); // 修改原始值 x = 20; printValue(ref_x); return 0; } -
3、多线程调用
代码中使用了 std::thread 来启动两个线程,分别调用 FindHomography 和 FindFundamental 方法。
线程 threadH
thread threadH(&Initializer::FindHomography, this, ref(vbMatchesInliersH), ref(SH), ref(H));
-
&Initializer::FindHomography:指向Initializer类的成员函数FindHomography。 -
this:当前对象的指针,用于传递给成员函数。 -
ref(vbMatchesInliersH):使用std::ref包装的vbMatchesInliersH引用,确保传递的是引用而不是值。 -
ref(SH):使用std::ref包装的SH引用。 -
ref(H):使用std::ref包装的H引用
线程 threadF
thread threadF(&Initializer::FindFundamental, this, ref(vbMatchesInliersF), ref(SF), ref(F));
&Initializer::FindFundamental:指向Initializer类的成员函数FindFundamental。this:当前对象的指针,用于传递给成员函数。ref(vbMatchesInliersF):使用std::ref包装的vbMatchesInliersF引用。ref(SF):使用std::ref包装的SF引用。ref(F):使用std::ref包装的F引用。
实际应用
在实际应用中,启动
线程后需要确保线程能够正确地完成任务。通常需要等待所有线程完成后再继续执行后续代码。这可以通过 std::thread 的 join 方法来实现:
bool Initializer::Initialize(const Frame &CurrentFrame) {
// ...
thread threadH(&Initializer::FindHomography, this, ref(vbMatchesInliersH), ref(SH), ref(H));
thread threadF(&Initializer::FindFundamental, this, ref(vbMatchesInliersF), ref(SF), ref(F));
// 等待线程完成
threadH.join();
threadF.join();
// 继续执行其他初始化步骤
// ...
return true; // 或者根据实际情况返回适当的值
}
4、三元运算符
代码举例
std::cout << "Sensor type: " << (m_sensor == eSensor::MONOCULAR ? "Monocular" : (m_sensor == eSensor::STEREO ? "Stereo" : "RGB-D")) << std::endl;
在这行代码中,三元运算符是嵌套使用的,以便处理多个条件。让我们逐步拆解:
-
外层三元运算符:
m_sensor == eSensor::MONOCULAR ? "Monocular" : (...)- 条件:
m_sensor == eSensor::MONOCULAR - 如果条件为
true:返回字符串"Monocular" - 如果条件为
false:执行内层三元运算符
- 条件:
-
内层三元运算符:
m_sensor == eSensor::STEREO ? "Stereo" : "RGB-D"- 条件:
m_sensor == eSensor::STEREO - 如果条件为
true:返回字符串"Stereo" - 如果条件为
false:返回字符串"RGB-D"
- 条件:
5、枚举类型 eSensor
在 C++ 中,枚举类型(enum)是一种用户定义的数据类型,用于定义一组命名的整数常量。枚举类型可以提高代码的可读性和可维护性,因为它为特定的值赋予了有意义的名称。
类型
enum class eSensor {
MONOCULAR,
STEREO,
RGBD
};
解释
-
enum class:enum class是 C++11 引入的一种强类型枚举。与传统的enum不同,enum class的枚举值具有强类型检查,不能与其他枚举类型或整数类型混用。- 例如,
eSensor::MONOCULAR是eSensor类型的,不能直接赋值给int类型的变量。
-
枚举值:
MONOCULAR:表示单目传感器。STEREO:表示立体传感器。RGBD:表示 RGB-D 传感器(深度传感器)。
声明和初始化
eSensor sensorType = eSensor::MONOCULAR;
条件判断
if (sensorType == eSensor::MONOCULAR) {
std::cout << "Using Monocular sensor." << std::endl;
} else if (sensorType == eSensor::STEREO) {
std::cout << "Using Stereo sensor." << std::endl;
} else if (sensorType == eSensor::RGBD) {
std::cout << "Using RGB-D sensor." << std::endl;
}
作为函数参数
void configureSensor(eSensor sensor) {
switch (sensor) {
case eSensor::MONOCULAR:
std::cout << "Configuring Monocular sensor." << std::endl;
break;
case eSensor::STEREO:
std::cout << "Configuring Stereo sensor." << std::endl;
break;
case eSensor::RGBD:
std::cout << "Configuring RGB-D sensor." << std::endl;
break;
default:
std::cout << "Unknown sensor type." << std::endl;
break;
}
}
示例代码
下面是一个完整的示例,展示了如何定义和使用 eSensor 枚举类型:
#include <iostream>
#include <string>
// 定义枚举类型 eSensor
enum class eSensor {
MONOCULAR,
STEREO,
RGBD
};
// 定义 System 类
class System {
public:
// 构造函数
System(const std::string &strVocFile, std::string &strSettingsFile, const eSensor sensor, const bool bUseViewer = true)
: m_strVocFile(strVocFile), m_strSettingsFile(strSettingsFile), m_sensor(sensor), m_bUseViewer(bUseViewer) {
// 初始化系统
std::cout << "Initializing system with vocabulary file: " << m_strVocFile << std::endl;
std::cout << "Settings file: " << m_strSettingsFile << std::endl;
// 使用三元运算符输出传感器类型
std::string sensorType = (m_sensor == eSensor::MONOCULAR ? "Monocular" :
(m_sensor == eSensor::STEREO ? "Stereo" : "RGB-D"));
std::cout << "Sensor type: " << sensorType << std::endl;
std::cout << "Use viewer: " << (m_bUseViewer ? "Yes" : "No") << std::endl;
}
private:
std::string m_strVocFile;
std::string m_strSettingsFile;
eSensor m_sensor;
bool m_bUseViewer;
};
int main() {
std::string vocFile = "vocabulary.txt";
std::string settingsFile = "settings.yaml";
// 创建 System 对象
System system(vocFile, settingsFile, eSensor::STEREO);
return 0;
}
输出结果
运行这段代码后,控制台的输出将是:
Initializing system with vocabulary file: vocabulary.txt
Settings file: settings.yaml
Sensor type: Stereo
Use viewer: Yes
467

被折叠的 条评论
为什么被折叠?



