请考虑以下代码.在Unordered_map中使用Key中的数组有什么好的散列函数?
#include <unordered_map>
using namespace std;
enum TriState {
S0 = -1,
S1 = 0,
S2 = +1
};
struct K { // Key for the map
TriState a[8][8];
bool operator==(const K& k1) const {
for (int i = 0; i < 64; i++)
if (k1.a[0][i] != a[0][i])
return false;
return true;
}
};
struct Hash {
size_t operator()(const K& k) const {
size_t s;
// s = what is a good hash value?
return s;
}
};
unordered_map<K, int, …Run Code Online (Sandbox Code Playgroud) 考虑一个标准迭代器,它需要为遍历数据结构分配内存.如果无法分配内存,标准是否允许迭代器抛出异常?例如,考虑树数据结构的输入迭代器.在这种情况下,要遍历树,您必须添加并维护指向每个节点的父节点的指针(这将减慢不需要这样的指针的操作,如树上的插入/擦除/查找)或使用堆栈帮助迭代器存储指向遍历节点的指针.在这种情况下,虽然推进堆栈可能会增长,直到没有更多的空闲内存并且迭代器被迫抛出.
例如,考虑使用Splay树实现的std :: map.这种树结构是可变的,每次访问地图进行读取时都会发生变化.当地图是常量时,谁必须确认并发读数的隔离,是由用户代码还是地图实现?
假设您具有以下非静态成员函数:
// .h
struct C {
void f();
}
Run Code Online (Sandbox Code Playgroud)
现在假设您希望C::f通过使用一些特定的子函数来实现C::f,以使其更短且更易读; 例如:
// .cpp
void C::f() {
h1();
h2();
//...
hn();
}
Run Code Online (Sandbox Code Playgroud)
假设许多h()函数不需要访问任何数据成员.这意味着您可以将函数定义为静态自由函数(在一个.cpp中)或作为成员函数(静态或非静态).
你会让它们成为静态自由函数或C的函数成员吗?
第一种情况的一个优点是您不必在以下情况下声明它们C:
// .cpp
static void h1() {//...}
static void h2() {//...}
static void hn() {//...}
Run Code Online (Sandbox Code Playgroud)
此外,如果我没有错,则不存在全局命名空间污染的风险,因为它们是静态的,即它们只能从同一单元.cpp内的其他函数中看到(其中C :: f也被定义).
而在第二种情况下,你将不得不声明它们C,虽然,正如我所说,它们只应该被使用C::f.
// .h
struct C {
void f();
private:
static void h1(); // can be either static or non-static
static void h2();
static void hn();
}
// …Run Code Online (Sandbox Code Playgroud) 我boost::log用作我的C++程序的记录器.在开发过程中,我经常以这种方式使用它,例如:
#define LOG(severity) BOOST_LOG_SEV(boost::logger::get(), (severity))
#define LOG_ERR LOG(Severity::error)
#define LOG_INFO LOG(Severity::info)
#define LOG_DEBUG LOG(Severity::debug)
Run Code Online (Sandbox Code Playgroud)
这里BOOST_LOG_SEV是所提供的设施boost::log,同时LOG,LOG_ERROR,LOG_INFO,LOG_DEBUG是由我定义的快捷键.
简而言之,BOOST_LOG_SEV动态地将当前调试严重性与传递给宏本身的严重性进行比较,以决定是否发出输出.
这是一个使用上述宏进行调试的程序示例:
// set at compile time
#define MAX_LOG_SEVERITY Severity::debug
int main() {
// Print all the messages with a
// Severity <= MAX_LOG_SEVERITY defined before compiling
boost::log::set_severity(boost::logger::get(), MAX_LOG_SEVERITY); // set_severity() is fictitious just to give you an idea
// bool err = ...
if (err)
LOG_ERR << "An …Run Code Online (Sandbox Code Playgroud) 我正在实施一种类型T.虽然这不是必需的,但是这种类型的用户可能会受益于移动语义,即T(T&&)和T& operator=(T&&).
由于T包含std::function作为成员数据,我无法使用noexcept保证来实现移动语义,这对用户来说T 不那么有用.
另外,由于上述原因,我的实现不能像以下那样简单:T(&&) noexcept = default和T& operator=(T&&) noexcept = default
替代方案是向用户提供非noexcept版本:T(&&) = default和T& operator=(T&&) = default; 或者实现我的用户定义的noexcept移动语义std::function::swap()(保证是这样noexcept).在后一种情况下,遗憾的是我不得不照顾除了std::function(丑陋!)以外的所有其他成员数据.
所以,有三种选择:
T(&&) = default和T& operator=(T&&) = defaultT(&&) noexcept {/* lot of code */}和T& operator=(T&&) noexcept {/* lot of code */}我知道这个问题相当主观,但你会选择什么?
任何人都可以解释为什么在第三版C++编程语言的第13章中,Stroustrup说明了函数模板的默认参数,尽管C++(pre C++ 11)不支持它们?这是Stroustrup在第13.4.1节中给出的示例:
明确指定每个调用的比较是繁琐的.幸运的是,很容易选择默认值,因此只需要明确指定不常见的比较条件.这可以通过重载来实现:
Run Code Online (Sandbox Code Playgroud)template<class T, class C> int compare(const String<T>& str1, const String<T>& str2); // compare using C template<class T> int compare(const String<T>& str1, const String<T>& str2); // compare using Cmp<T>或者,我们可以提供普通约定作为默认模板参数:
Run Code Online (Sandbox Code Playgroud)template <class T, class C = Cmp<T> > int compare(const String<T>& str1, const String<T>& str2)
这是编译器错误:
错误:默认模板参数可能不在函数模板中使用
请考虑以下代码:
struct T {
int a;
union {
struct {
int a;
} s1;
struct {
char b[1024];
} s2;
};
};
int main() {
T x = T();
}
Run Code Online (Sandbox Code Playgroud)
由于调用了显式构造函数,上面的代码最终将零初始化为x中的所有数据成员.
但即使未调用显式,我也希望x初始化为零.要做到这一点,一个想法是在他们的声明中初始化数据成员,这对于T :: a来说似乎没问题.但是,如何使用相同的标准对联合占用的所有内存进行零初始化?
struct T {
int a = 0;
union {
struct {
int a;
} s1;
struct {
char b[1024];
} s2;
};
};
int main() {
T x; // I want x to be zero-initialized
}
Run Code Online (Sandbox Code Playgroud) 假设条件变量上有N个等待线程(读取器),这些线程由另一个线程(生产者)通知.现在所有N个读者都会尝试拥有他们所引用的unique_lock,一次一个.现在假设生产者想要再次锁定相同的unique_lock,出于某些原因,在任何那些醒来的读者甚至开始拥有锁之前.按照标准,是否有保证生产者只有在所有通知读者开始锁定步骤后才能成功(尝试)进入其关键部分?
考虑以下由两个 组成的完整程序TU:
// 1.cpp
bool init() { /* ... */ }
const auto _{init()};
// 2.cpp
int main() {}
Run Code Online (Sandbox Code Playgroud)
问题:是否可以保证 _ 在某个时候初始化(我不在乎什么时候)?
现在考虑由一个组成的程序TU:
// 1.cpp
bool init() { /* ... */ }
const auto _{init()};
int main() {}
Run Code Online (Sandbox Code Playgroud)
请注意 _ 不是odr-used。
但是,main()在第二种情况下,是否可以说是odr-used,因为它在程序运行时被调用时(有点)“被实现引用”?
如果main()是odr-used,这是否意味着 _ 保证被初始化,即使它不是odr-used?
编辑:
这就是en.cppreference.com关于延迟动态初始化的说法:
如果没有从给定的翻译单元 odr 使用变量或函数,则该翻译单元中定义的非局部变量可能永远不会被初始化(这对按需动态库的行为进行建模)
在阅读我的两个例子时,你能回答我的问题吗?