初始化列表表达式非常便于初始化C++容器:
std::vector<int>({1, 2, 3})
Run Code Online (Sandbox Code Playgroud)
......但似乎一个括号内的初始化列表表达式,如{1,2,3}
将只绑定到需要的功能std::initializer_list<int>
-它并不似乎绑定到一个通用(转发)参考:
template <class T>
void foo(T&& v)
{
std::vector<int>(std::forward<T>(v));
}
int main()
{
foo({1, 2, 3})
}
Run Code Online (Sandbox Code Playgroud)
这输出:
test2.cpp:11:6: note: template<class U> void foo(U&&)
test2.cpp:11:6: note: template argument deduction/substitution failed:
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’
Run Code Online (Sandbox Code Playgroud)
(这是GCC 4.7.2的结果.)
遗憾的是,这意味着我们无法转发初始化列表表达式.既然这样做很方便,我想问为什么这不起作用?为什么括号封闭的初始化列表表达式不能绑定到转发引用?或者这是允许的,也许我的编译器太老了?
Python中的短语"keyword only args"有点含糊不清 - 通常我认为它是指传递给**kwarg
参数的args .但是,该inspect
模块似乎区分了**kwarg
一个名为"仅关键字参数"的东西.
来自文档:
inspect.getfullargspec(FUNC)
获取Python函数参数的名称和默认值.返回一个命名元组:
FullArgSpec(args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, annotations)
args
是参数名称的列表.varargs
并且varkw
是*
和**
参数的名称或None
.defaults是最后n个参数的默认值的n元组,如果没有默认参数,则为None.kwonlyargs
是仅关键字参数名称的列表.kwonlydefaults
是一个将名称映射kwonlyargs
到默认值的字典.annotations
是将参数名称映射到注释的字典.
因此,检查模块有一些叫做kwonlyargs
和的东西kwonlydefaults
.这在实际的功能签名中意味着什么?如果你有一个接受**kwarg
参数的函数签名,那么直到运行时你才能真正知道关键字参数的名称,因为调用者基本上只能传递任意字典.那么,kwonlyargs
在函数签名的上下文中有什么意义- 这就是它所inspect.getfullargspec
提供的.
C++ 11标准(或至少是本工作草案)要求实现该Allocator
概念的类提供复制构造函数.
当所有分配器都必须是无状态时,这有意义,但是当在分配器类中允许状态时,提供复制构造函数可能并不可取.例如,如果分配器实现某种slab分配系统或内存池,则它维护一个内部freelist.在我看来,应该始终移动这样的分配器,而不是复制.实际上复制它需要分配新的存储,然后完全复制原始分配器的内部状态,包括所有空闲内存块,空闲列表等.(或者"复制" Allocator
只是意味着返回Allocator()
,即返回一个新的默认构造分配器?)
实际上复制一个有状态的分配器似乎是完全没有必要的,因为据我所知,实际上没有真正的通用用例来复制构造一个分配器.Container
实际上没有复制分配器--C++ 11容器将Allocator::select_on_container_copy_construction
在容器拷贝构造函数中调用,而这通常只返回Allocator()
.然后容器通常只是从另一个容器中逐个元素地复制,可能只是通过调用Container::insert
.
当然,优化的容器实现可能会使用有关容器结构的内部知识来执行更复杂的操作,但仍然没有人会复制构造other.get_allocator()
- Container将只调用other.get_allocator().select_on_container_copy_construction()
以获取默认构造的分配器.
那么为什么我们要求分配器本身必须是可复制构造的呢?不应该移动施工是否足够?
注意:要清楚,这个问题与c ++中的allocator为什么需要复制构造函数不重复?.那个问题是专门询问std::allocator
(这是无状态的),而我问的是实现这个Allocator
概念的自定义分配器.
我有一系列重叠的问题,最好的问题是:
在什么情况下#
,URL 中的字符(锚)触发HTTP提取,在一个<a href
或一个<img src
?的上下文中?
通常,应该:
http://foo.com/bar.html#1
Run Code Online (Sandbox Code Playgroud)
和
http://foo.com/bar.html#2
Run Code Online (Sandbox Code Playgroud)
需要两个不同的HTTP提取?我认为答案肯定是否定的.
更具体的细节:
提示这个问题的情况是我第一次尝试使用SVG堆叠 - 这种技术可以将多个图标嵌入到单个svg
文件中,因此只需要一个HTTP请求.本质上,我们的想法是您将多个SVG图标放在一个文件中,并使用CSS隐藏所有这些图标,但使用CSS :target
选择器选择的除外.
然后#
,当您img
在HTML中编写元素时,可以使用URL中的字符选择单个图标:
<img
src="stacked-icons.svg#icon3"
width="80"
height="60"
alt="SVG Stacked Image"
/>
Run Code Online (Sandbox Code Playgroud)
当我在Chrome上试用它时,效果非常好.发出单个HTTP请求,并且可以svg
使用不同的锚点/目标通过相同的URL 显示多个图标.
但是,当我尝试使用Firefox(28)时,我通过控制台看到发出了多个 HTTP请求 - 每个svg URL一个!所以我看到的是:
GET http://myhost.com/img/stacked-icons.svg#icon1
GET http://myhost.com/img/stacked-icons.svg#icon2
GET http://myhost.com/img/stacked-icons.svg#icon3
GET http://myhost.com/img/stacked-icons.svg#icon4
GET http://myhost.com/img/stacked-icons.svg#icon5
Run Code Online (Sandbox Code Playgroud)
...当然,这首先违背了使用SVG堆叠的目的.
有没有什么原因Firefox会为每个网址发出单独的HTTP请求,而不是img/stacked-icons.svg
像Chrome一样只提取一次?
这导致了更广泛的问题 - 什么规则确定#
URL中的字符是否应该触发HTTP请求?
我正在研究非垃圾收集环境(如C或C++)中无锁数据结构的各种类型的内存回收策略.
在我的实验中,我成功地实施了一些这样的策略 - 特别是基于静态状态的回收(QSBR)和基于纪元的回收(EBR).
我的问题涉及这两种策略之间的主要区别之一.
首先,我知道QSBR和EBR如何工作,并成功实施了这两种策略.QSBR和EBR实际上非常相似.它们都是延迟回收策略 - 意思是,它们在通过简单地推迟实际释放来释放内存时避免竞争条件,直到可以证明释放内存是安全的.对于QSBR和EBR,这是使用全局"纪元计数器",然后是每个参与线程的各种线程本地纪元计数器来实现的.
QSBR和EBR之间的主要区别在于,使用QSBR,您基本上可以指示线程何时没有任何对任何共享数据的引用.随着EBR,你表明当一个线程确实有对共享数据的参考.因此,在实践中,使用EBR的代码最终看起来更像传统的互斥锁定/解锁关键部分,如:
enter_critical_section();
/* do some cool lock-free stuff */
exit_critical_section();
Run Code Online (Sandbox Code Playgroud)
...而对于QSBR,它更像是:
/* do some cool lock-free stuff */
quiescent_state(); // this thread is done using shared data
Run Code Online (Sandbox Code Playgroud)
所以他们非常相似.但是,我不太了解的一个关键问题是所有文献都表明在实践中,QSBR有一个主要缺点:它需要应用程序级支持,这意味着它不适合在通用库中使用.
这在无数期刊文章或图书馆文献中都有提及,例如在http://www.cs.toronto.edu/~tomhart/papers/tomhart_thesis.pdf中,它说:
QSBR与应用有关的事实是QSBR和EBR之间的根本区别.根据定义,EBR可以检测库级别的宽限期.相比之下,QSBR要求应用程序向QSBR库报告静止状态.正如我们在5.2节中所示,这使QSBR具有显着的性能优势
用户空间RCU项目的文档使用了QSBR的变体,也说了类似的东西:
但是,每个线程必须定期调用rcu_quiescent_state(),就像在内核中一样,必须定期调用schedule().执行RCU读取端关键部分的每个线程还必须在线程创建之后调用rcu_register_thread(),并在线程退出之前调用rcu_unregister_thread().这些要求显然严格限制了整个应用程序设计,例如,禁止在大多数库代码中使用QSBR RCU,但作为回报,QSBR提供了无与伦比的性能.
我很难理解为什么会出现这样的问题.我在这里收集的是,使用QSBR,应用程序需要指示它何时进入静止状态.但我不明白为什么在图书馆层面这么难?
提供堆栈和队列等数据结构的无锁库是否只能表明它在每次操作完成后进入静止状态?为什么有关于QSBR的所有这些警告表明它在库代码中以某种方式不易使用而不是应用程序代码?
algorithm multithreading memory-management thread-safety lock-free
Boost库提供了一个方便的功能hash_value
,基本上只是调用:
return hash<T>()(key);
Run Code Online (Sandbox Code Playgroud)
据我所知,包含的C++ 11 std::hash
非常相似boost::hash
,但没有包含std::hash_value
.这需要应用程序代码来创建一个hash
对象并调用它,operator()
而不是只调用一个方便的函数.有什么理由std::hash_value
没有标准化吗?
在我正在进行的了解 DNS 的实验中,我试图了解名称服务器如何进行递归查询。我得到了基本的想法 - 你从顶级 dns 服务器开始,然后它向你发送要联系的权威域名服务器列表,然后你联系这些服务器等,直到你得到权威响应。
听起来很简单。
但当我在实践中尝试时,第一步后我就陷入了困境。我只是使用命令行工具手动执行此操作 - (我确保关闭递归。)
好的,第一步:从根名称服务器开始。我从Wikipedia 上的根名称服务器198.41.0.4
列表中随机选择了 (Verisign) 。
我向其发送解析“google.com”的请求。
它向我发回以下内容:
+---------------------------------------------------------------------------+
| 47547 | QR: 1 | OP: 00 | AA: 0 | TC: 0 | RD: 1 | RA: 0 | Z: 0 | RCODE: 00 |
+---------------------------------------------------------------------------+
| QDCOUNT: 1, ANCOUNT: 0, NSCOUNT: 13, ARCOUNT: 15 |
+---------------------------------------------------------------------------+
ANSWERS : 0
AUTHORITIES:
NS: m.gtld-servers.net
NS: l.gtld-servers.net
NS: k.gtld-servers.net
NS: j.gtld-servers.net
NS: i.gtld-servers.net
NS: h.gtld-servers.net
NS: g.gtld-servers.net …
Run Code Online (Sandbox Code Playgroud) C++标准容器和分配器为容器使用的指针类型提供typedef,即:
typename std::vector<T>::pointer
typename std::vector<T>::const_pointer
Run Code Online (Sandbox Code Playgroud)
用于创建typedef的实际指针类型通过确定 std::allocator_traits
typedef typename std::allocator_traits<Allocator>::pointer pointer;
Run Code Online (Sandbox Code Playgroud)
由于每个容器也有一个value_type
类型定义,想必目的pointer
的typedef是一些奇怪的情况下使用的指针类型的东西其他比value_type*
.我从来没有亲自看到类似的用例,但我认为标准委员会希望提供使用容器的自定义指针类型的可能性.
问题是,这似乎与为其中的函数提供的定义不一致std::allocator_traits
.具体来说,std::allocator_traits
我们有construct
函数,定义为:
template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);
Run Code Online (Sandbox Code Playgroud)
...只是打电话 a.construct(p, std::forward<Args>(args)...)
但请注意,此函数不对自定义指针类型进行任何规定.该参数p
是一个普通的本机指针.
那么,为什么这个函数的定义不是这样的:
template <class... Args>
static void construct(Alloc& a, typename Alloc::pointer p, Args&&... args);
Run Code Online (Sandbox Code Playgroud)
似乎没有这个,std::allocator_traits<Alloc>::construct
如果与定义了一些自定义指针类型的Allocator一起使用,那么使用的容器将会失败.
那么,这里发生了什么?或者我是否误解pointer
了首先使用typedef 的目的?
我对AF_PACKET
套接字系列(用于SOCK_RAW
套接字)与以太网(IEEE 802.3)的具体关系感到非常困惑。
到目前为止我的理解:
我了解 OSI 模型,以及以太网等第 2 层技术如何融入该模型。
我知道AF_PACKET
可以与SOCK_RAW
套接字一起使用来接收包含 14 字节以太网标头的数据报,然后是其他一些更高层协议标头,例如 IPv4、IPv6 等,然后是可选的传输层协议,如TCP,最后是有效载荷。
我知道您可以传递诸如ETH_P_ALL
或ETH_P_IP
作为协议参数的标志socket
来为您提供内核过滤数据包,只需向您发送包含某种类型标头的数据包。
AF_PACKET
系列创建的套接字可以接收或发送到类型为 的端点sockaddr_ll
,该端点与特定的 MAC 地址(EUI-48 地址)以及特定的网络接口(例如eth0
或其他)相关联。我不明白的是:
我不明白是否AF_PACKET
应该专门用于以太网设备,而不是其他第 2 层技术,例如 Wifi、蓝牙、令牌环、Infiniband 等。
我不明白以太网设备与使用 14 字节以太网标头的第 2 层协议之间的关系。以太网报头是 14 字节,可以定义为:struct eth_hdr { char dest_address[6]; char source_address[6]; uint16_t ethertype; };
换句话说,这个报头是否只用于物理以太网设备?似乎答案是否定的,因为如果我AF_PACKET
在环回接口上使用,我仍然会收到包含 14 字节以太网标头的数据包。但环回不是以太网设备。那么为什么它会收到包含以太网报头的数据包呢?
如果 …
一般来说,语法:
for k, v in pairs(t) do
....
end
Run Code Online (Sandbox Code Playgroud)
相当于:
for k, v in next, t do
....
end
Run Code Online (Sandbox Code Playgroud)
但如果t
有一个__pairs
metamethod怎么办?标准next()
功能会检查这个吗?如果没有,那么在迭代表时总是使用pairs
并且从不next()
直接调用是不是更好?