考虑以下片段:
#include <array>
int main() {
using huge_type = std::array<char, 20*1024*1024>;
huge_type t;
}
Run Code Online (Sandbox Code Playgroud)
显然它会在大多数平台上崩溃,因为默认堆栈大小通常小于 20MB。
现在考虑以下代码:
#include <array>
#include <vector>
int main() {
using huge_type = std::array<char, 20*1024*1024>;
std::vector<huge_type> v(1);
}
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是它也崩溃了!回溯(使用最近的 libstdc++ 版本之一)指向include/bits/stl_uninitialized.h文件,我们可以在其中看到以下几行:
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
std::fill(__first, __last, _ValueType());
Run Code Online (Sandbox Code Playgroud)
调整大小vector构造函数必须默认初始化元素,这就是它的实现方式。显然,_ValueType()临时会导致堆栈崩溃。
问题是它是否是一个符合要求的实现。如果是,那实际上意味着大类型向量的使用非常有限,不是吗?
我正在探索使用boost :: asio以及C++ 11功能.特别是,我专注于一个名为"async_tcp_echo_server.cpp"的示例,位于此处(代码也显示在我的问题的末尾):
我的问题涉及到tcp::socket成员socket_的的server类.在类的do_accept()方法中server,socket_传递给async_accept().(根据asio文档,async_accept()要求,作为其第一个参数,socket接受连接进入.)到目前为止,这么好.
下一个参数,即异步接受操作的回调,是一个lambda函数.lambda的主体构造一个新session对象,其构造函数也需要相同的对象socket.有趣的是,socket对象无法复制; 所以在这个例子中,使用了传递对象socket_成员的server对象std::move().
我知道"唯一的" socket_对象(它是对象的"永久"成员server)被"移动"到session对象中.精细 - socket物体不会被复制,而是被移动 - 每个人都很开心.
但是下次打电话会发生什么async_accept()?是否相同socket_(成员server),之前被移动,再次传入?当我们"移动"一个成员时,留下了什么?有无限socket物体的神奇喷泉吗?
或者这里发生的事情真的不那么明显了?当socket移入时session,"遗留/移动"对象(socket_成员server)的内容是否与"新" 对象自己的"尚未构建" 成员的内容交换?我甚至有意义吗?sessionsocket_
代码如下.程序流程相当简单.main()构造一个server对象.该 …
我阅读了boost asio http服务器示例代码(参见http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/example/cpp11/http/server/connection.cpp)并找到auto self(shared_from_this());变量是已在捕获范围([this, self])中使用.但自变量未在lambda函数中使用.那么这样做有什么好处?
学习c ++并尝试熟悉一些模式.该signals2 DOC显然有事情,我可以插槽和信号做繁多.我不明白的是我应该使用哪种类型的应用程序(用例).
我正在考虑调度变更事件的状态机.来自动态类型的背景(C#,Java等),您将使用事件调度程序或静态引用或回调.
使用跨类回调在c ++中是否存在困难?这就是为什么信号2存在的原因?
示例案例之一是文档/视图.这种模式如何比使用函数向量并在循环中调用每个函数更好地适用,或者说在注册的侦听类实例中调用状态更改的lambda?
class Document
{
public:
typedef boost::signals2::signal<void ()> signal_t;
public:
Document()
{}
/* Connect a slot to the signal which will be emitted whenever
text is appended to the document. */
boost::signals2::connection connect(const signal_t::slot_type &subscriber)
{
return m_sig.connect(subscriber);
}
void append(const char* s)
{
m_text += s;
m_sig();
}
const std::string& getText() const
{
return m_text;
}
private:
signal_t m_sig;
std::string m_text;
};
Run Code Online (Sandbox Code Playgroud)
和
class TextView
{
public: …Run Code Online (Sandbox Code Playgroud) 我的问题如下.我异步启动几个操作,我想继续,直到所有操作都完成.使用Boost Asio,最直接的方法如下.假设tasks某种对象容器支持一些异步操作.
tasksToGo = tasks.size();
for (auto task: tasks) {
task.async_do_something([](const boost::system::error_code& ec)
{
if (ec) {
// handle error
} else {
if (--taslsToGo == 0) {
tasksFinished();
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案的问题在于它感觉就像一个解决方法.在Boost 1.54中我可以用期货来做,但我只能同步等待,这只能从与run()被调用的地方分开的线程中进行.
for (auto task: tasks) {
futures.push_back(task.async_do_something(boost::asio::use_future));
}
for (auto future: futures) {
future.wait();
}
Run Code Online (Sandbox Code Playgroud)
这个代码比前一个代码更清晰,但是我需要一个我不想要的单独的代码.我想要一些可以像这样使用的东西:
for (auto task: tasks) {
futures.push_back(task.async_do_something(boost::asio::use_future));
}
boost::asio::spawn(ioService, [](boost::asio::yield_context yield)
{
for (auto future: futures) {
future.async_wait(yield);
}
tasksFinished();
}
Run Code Online (Sandbox Code Playgroud)
有什么可以类似地使用吗?
请考虑以下代码:
#include <type_traits>
template<template<class...> class T, class... U>
struct is_specialization_of : std::false_type{};
template<template<class...> class T, class... U>
struct is_specialization_of<T, T<U...>> : std::true_type{};
template<class T, class U = int>
struct test{};
// (1) ok
static_assert(is_specialization_of<test, test<int>>::value, "1");
template<class T>
using alias = test<T>;
// (2) fails
static_assert(is_specialization_of<alias, alias<int>>::value, "2");
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
为什么(2),即static_assert使用别名模板,失败?
(2)中的模板参数推导过程与(1)中的模板参数推导过程有何不同?
查看libstdc ++源代码,我发现以下declval实现:
template<typename _Tp, typename _Up = _Tp&&>
_Up __declval(int); // (1)
template<typename _Tp>
_Tp __declval(long); // (2)
template<typename _Tp>
auto declval() noexcept -> decltype(__declval<_Tp>(0));
Run Code Online (Sandbox Code Playgroud)
此实现是 Eric Niebler 提出的,用于优化编译时间:他解释说,重载解析比模板实例化更快。
但是,我不明白它是如何工作的。特别:
_Up不仅仅是返回_Tp&&?与最幼稚的实现相反,这一切如何防止模板实例化:
template<typename T>
T&& declval() noexcept;
Run Code Online (Sandbox Code Playgroud) 我不完全确定threading=multi在构建boost时旗帜到底是什么.文件说:
Causes the produced binaries to be thread-safe. This requires proper
support in the source code itself.
Run Code Online (Sandbox Code Playgroud)
这似乎不是很具体.这是否意味着对例如升级容器的访问受到保护mutexes/locks或类似的保护?由于我的代码性能至关重要,我想尽量减少任何不必要的互斥量等.
更多细节:
我的代码是一个插件DLL,它被加载到一个多线程的第三方应用程序中.我静态地将boost链接到DLL(除了标准的Windows DLL之外,插件不允许有任何其他依赖项,所以我不得不这样做).
虽然应用程序是多线程的,但我的DLL中的大多数函数只能从单个线程调用,因此无需保护对容器的访问.我明确地保护我的代码的剩余位置,可以通过使用boost::mutex和朋友从多个线程调用.
我试过建设提升既threading=multi与threading=single和似乎都工作,但我真的很想知道我在这里做.
asio库在很多例子中都传递了一个错误参数,即; http://think-async.com/Asio/asio-1.5.3/src/examples/echo/async_tcp_echo_server.cpp
这个参数有什么意义?asio实际上是否填充了此参数的错误?
如果我从处理程序函数中删除它,它编译得很好.
我正在尝试使用monitor/ mwait指令监视从设备到内存位置的DMA写入.在内核模块(char设备)中,我有一个在内核线程中运行的以下代码(非常类似于这段内核代码):
static int do_monitor(void *arg)
{
struct page *p = arg; // p is a 'struct page *'; it's also remapped to user space
uint32_t *location_p = phys_to_virt(page_to_phys(p));
uint32_t prev = 0;
int i = 0;
while (i++ < 20) // to avoid infinite loop
{
if (*location_p == prev)
{
__monitor(location_p, 0, 0);
if (this_cpu_has(X86_FEATURE_CLFLUSH_MONITOR))
clflush(location_p);
if (*location_p == prev)
__mwait(0, 0);
}
prev = *location_p;
printk(KERN_NOTICE "%d", prev);
}
}
Run Code Online (Sandbox Code Playgroud)
在用户空间中,我有以下测试代码:
int …Run Code Online (Sandbox Code Playgroud) c++ ×8
boost ×6
boost-asio ×4
c++11 ×4
boost-bind ×1
boost-build ×1
declval ×1
dma ×1
events ×1
future ×1
lambda ×1
libstdc++ ×1
linux-kernel ×1
move ×1
stdvector ×1
templates ×1
windows ×1
x86 ×1