我在用
unordered_map<string, int>
Run Code Online (Sandbox Code Playgroud)
和
unordered_map<int, int>
Run Code Online (Sandbox Code Playgroud)
在每种情况下使用什么散列函数以及在每种情况下碰撞的可能性是多少?我将分别在每种情况下插入唯一字符串和唯一int作为键.
我很想知道在字符串和int键及其碰撞统计数据的情况下哈希函数的算法.
考虑这个简单的层次
class Base { public: virtual ~Base() { } };
class Derived : public Base { };
Run Code Online (Sandbox Code Playgroud)
试图向下转换Base* p到Derived*可能使用dynamic_cast<Derived*>(p).我曾经dynamic_cast通过将vtable指针p与Derived对象中的指针进行比较来思考作品.
但是,如果我们从中衍生出另一个类Derived呢?我们现在有:
class Derived2 : public Derived { };
Run Code Online (Sandbox Code Playgroud)
在这种情况下:
Base* base = new Derived2;
Derived* derived = dynamic_cast<Derived*>(base);
Run Code Online (Sandbox Code Playgroud)
我们仍然得到一个成功的向下转换,即使vtable指针in Derived2与vtable指针无关Derived.
它是如何实际工作的?如何dynamic_cast知道是否Derived2派生自Derived(如果Derived在不同的库中声明的话)?
我正在寻找关于它如何实际工作的具体细节(最好是在海湾合作委员会,但其他人也很好).这个问题是不是一个重复这个问题(没有指明它是如何工作).
什么是芹菜相当于一个multiprocessing.JoinableQueue(或gevent.queue.JoinableQueue)?
我正在寻找的功能是能够.join()从发布者那里获得Celery任务队列,等待队列中的所有任务完成.
等待初始AsyncResult或GroupResult不足够,因为队列由工作人员自己动态填充.
我正在用 C 创建一个哈希表的实现,用于教育目的。
哈希函数应返回 size_t 哈希值。由于size_t的大小在不同的平台上是不同的(并且我想使用散列函数来对size_t中的所有位进行散列),所以我想到为不同的大小创建不同的散列函数。由于哈希函数将用作函数指针,我怀疑编译器无法像这样内联代码:
size_t hash4(void* key, size_t size);
size_t hash8(void* key, size_t size);
size_t hash(void* key, size_t size)
{
if (sizeof(size_t) == 4)
{
return hash4(key, size);
}
else if (sizeof(size_t) == 8)
{
return hash8(ket, size);
}
}
size_t (*hashFunc)(void* key, size_t size) = hash;
Run Code Online (Sandbox Code Playgroud)
每次调用哈希函数时都会使用两级间接。
这就是为什么我想到做这样的事情:size_t (*hashFunc)(void* key, size_t size) = hash##sizeof(size_t);相反。将仅使用一级间接。问题是 sizeof 运算符在前置阶段不可用。
那么定义一个预处理器值的好方法是什么,该值将在每个平台上扩展为正确的 size_t 大小?我想我可以检查预定义的宏,但我想知道是否有更好的方法。
我-MM在GCC中使用该标志来生成对象的makefile依赖项.makefile简要如下:
-include autodep
...
$(TARGET): build $(OBJECTS)
$(CC) -shared -o $@ $(OBJECTS)
$(CC) -MM $(SOURCES) > autodep
Run Code Online (Sandbox Code Playgroud)
源位于文件夹中src.但是,该autodep文件将包含没有相对路径的对象目标:
foo.o: src/foo.c src/foo.h
bar.o: src/bar.c src/bar.h src/baz.h
Run Code Online (Sandbox Code Playgroud)
我应该怎么把它变成这个:
src/foo.o: src/foo.c src/foo.h
src/bar.o: src/bar.c src/bar.h src/baz.h
Run Code Online (Sandbox Code Playgroud)
?
我尝试使用该-MT标志,但它似乎完全丢弃了对象目标.
我最近才发现,复合赋值运算符(例如operator+=或operator-=)可以在类范围之外重载。
考虑:
class X { }; // A third party class
// The following function is legal:
X& operator+=(X& lhs, const X& rhs) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
显然,非成员函数不能接触的私有接口X,因此这里没有封装问题。但这确实使它看起来像是X自己的接口的一部分,但显然不是。
在我看来,这可能会导致严重的代码滥用和混乱的行为。想象一下,有人认为将其用于带有“” std::vector或“”等标准内容的“聪明的黑客”会很好std::map。
这是特别的,因为其他操作符(例如operator[]和operator->不能成为非成员函数),我认为这就是这个原因。
那么为什么允许呢?
考虑名称空间内的类。该类的定义声明了一个朋友函数。
namespace Foo
{
class Bar
{
friend void baz();
};
}
Run Code Online (Sandbox Code Playgroud)
根据我所知道的,这应该声明baz()为最内部封闭的命名空间(即)的成员Foo。
因此,我希望以下定义baz()是正确的:
void Foo::baz() { }
Run Code Online (Sandbox Code Playgroud)
但是,GCC(4.7)给我一个错误。
error: ‘void Foo::baz()’ should have been declared inside ‘Foo’
Run Code Online (Sandbox Code Playgroud)
几种解决方案似乎有效:
baz()在课堂外宣布。
namespace Foo
{
void baz();
class Bar
{
friend void baz();
};
}
Run Code Online (Sandbox Code Playgroud)baz()在名称空间内定义。
namespace Foo
{
class Bar
{
friend void baz();
};
}
...
namespace Foo
{
void baz() { }
}
Run Code Online (Sandbox Code Playgroud)使用该-ffriend-injection标志进行编译,从而消除了错误。
这些解决方案似乎与我知道的C ++中声明/定义的一般规则不一致。
为什么我必须申报baz()两次? …
更新2
为什么这标记重复?Where and why do I have to put the “template” and “typename” keywords?不回答这个问题.这里描述的行为在任何地方都没有提到(你不会找到关于auto那里的预期行为的单一评论).
这不是重复,特别是因为在不同的编译器中存在冲突的行为.
UPDATE
就像GCC一样,clang也无法编译:
17 : error: expected expression
return p->is<true>();
^
Run Code Online (Sandbox Code Playgroud)
但是,在MSVC上,具有auto检测的代码正在成功编译.
显然,某处存在编译器错误.
考虑以下课程:
struct A {
template<bool>
bool is() const {
return true;
}
template<bool>
static A* get() {
static A a;
return &a;
}
};
Run Code Online (Sandbox Code Playgroud)
如果是模板功能,如
template<bool cond>
bool foo() {
auto p = A::get<cond>();
return p->is<true>();
} …Run Code Online (Sandbox Code Playgroud)