使用C++模板进行元编程时,是否有一种方法可以像调试器一样使用,以逐步实现模板的实例化和编译?现在看来,当创建一个复杂的模板网络时,除了查看编译器错误消息以查看模板是如何实例化的(如果有任何编译器错误),除了查看模板之外,确实没有很好的调试方法,并且如果生成了意外的事情,则尝试从错误消息向后工作.我不确定我正在寻找的是否存在,因为它必须是在编译时完成的事情,但基本上它将是一种方法,有点像逐步执行代码并检查堆栈帧gdb在运行时,可以停止编译器并检查环境以查找实例化模板或嵌套模板集的序列.
例如,假设我创建了一些简单的代码,如下所示:
template<typename T, typename R = void>
struct int_return_type {};
template<typename R>
struct int_return_type<int, R>
{
typedef R type;
};
template<typename T, typename R = void>
struct float_return_type {};
template<typename R>
struct float_return_type<float, R>
{
typedef R type;
};
template<typename T>
typename int_return_type<T>::type test()
{
cout << "T type is int" << endl;
}
template<typename T>
typename float_return_type<T>::type test()
{
cout << "T type is float" << endl;
}
int main()
{
test<int>();
test<float>();
return 0;
} …Run Code Online (Sandbox Code Playgroud) 为什么POSIX互斥量被认为比futex更重或更慢?pthread互斥锁类型的开销来自哪里?我听说pthread互斥体基于互斥体,当无争议时,不要对内核进行任何调用.那时似乎pthread互斥体只是一个围绕futex的"包装器".
开销只是在函数包装调用中,并且需要互斥函数来"设置"futex(即,基本上是pthread互斥函数调用的堆栈设置)?或者pthread互斥锁是否有一些额外的内存屏障步骤?
在C++ 11标准,部分1.10/5提到,但不正式定义的术语acquire operation,release operation和consume operation.然后在第29节继续使用这些术语来描述某些内存排序,原子操作和内存栅栏的操作.例如,关于"顺序和一致性"的29.3/1表示:
memory_order_release,memory_order_acq_rel和memory_order_seq_cst:存储操作在受影响的内存位置上执行释放操作 [强调添加].
这种类型的语言在第29节中重复出现,但令我烦恼的是,memory_order枚举的所有含义都基于操作类型,这些类型本身似乎没有被标准正式化,但必须对它们有一些共同的意义.作为定义有效.
换句话说,如果我说"一个酒吧是一个翻转的foo",bar和foo的具体含义是模棱两可的,因为这两个术语都没有正式定义.只定义了它们的相对性质.
请问C++的11个标准,或其他一些C++ 11标准委员会文件正式准确定义的是什么acquire operation,release operation等等是,或者是这些简单的通常理解的术语?如果是后者,是否有一个很好的参考被认为是这些操作含义的行业标准?我特别要求,因为硬件内存一致性模型不是相同的,因此我认为必须有一些共同商定的引用,允许那些实现编译器等的人正确地将这些操作的语义转换为本机程序集命令.
我一直在研究STM(软件事务内存)实现,特别是在利用锁的算法上,并且不依赖于垃圾收集器的存在,以保持与非托管语言(如C/C++)的兼容性.我已经阅读了Herlihy和Shavit的"多处理器编程艺术"中的STM章节,并阅读了几篇描述他的"事务锁定"和"事务锁定II" STM实现的Shavit论文.他们的基本方法是利用存储全局版本时钟和锁定值的散列表来确定另一个线程的写入是否触及了内存位置.据我了解算法,当执行写入事务时,读取版本时钟并将其存储在线程本地存储器中,并且还在线程本地存储器中创建读取集和写入集.然后执行以下步骤:
如果上述任何检查步骤失败(即步骤#1,#3和#5),则中止写入事务.
读事务的过程要简单得多.根据Shavit的论文,我们简单地说
如果步骤#2或#4失败,则中止读取事务.
我在脑海中似乎无法解决的问题是,当您尝试读取位于堆中的对象内的内存位置,而另一个线程调用delete指向该对象的指针时会发生什么?在Shavit的论文中,他们详细解释了如何不对已经被回收或释放的内存位置进行写入,但似乎在读取事务中,没有什么可以阻止可能的时序场景从另一个线程释放的对象内部的内存位置读取.例如,请考虑以下代码:
Thread A 在原子读事务中执行以下命令: linked_list_node* next_node = node->next;
Thread B 执行以下操作: delete node;
由于next_node是一个线程局部变量,它不是一个事务对象.为其分配值所需的解除引用操作node->next实际上需要两个单独的读取.在这些读取之间,delete可以调用node,以便成员的读取next实际上是从已经释放的一段内存中读取.由于读是乐观的,内存的释放指向node中Thread B不会被检测到Thread A.这不会导致可能的崩溃或分段错误吗?如果是这样的话,如何在不锁定读取的内存位置的情况下避免这种情况(教科书和论文表示的内容都是不必要的)?
我最近了解到,如果你有一个类作为函数参数的引用,那么将某些所需的信息作为局部变量存储,而不是每次在函数中需要时访问类成员都是更好的实践和更有效的方法.
所以...
void function(const Sphere& s)
{
//lots of calls to s.centre and s.radius
}
Run Code Online (Sandbox Code Playgroud)
要么
void function(const Sphere& s)
{
Vector3 centre = s.centre; float radius = s.radius;
//an equal amount of calls to centre and radius
}
Run Code Online (Sandbox Code Playgroud)
我被告知第二个更好,但为什么?而且,哪里是一个开始更充分地研究这个问题的好地方?(请给dummys!)
pwrite()在尝试写入超过2GB的偏移时,我似乎在OSX 10.6.8上遇到了一个奇怪的问题.我一直在捕捉SIGXFSZ信号,这意味着已超出文件大小限制.忽略信号无济于事,因为它pwrite()会简单地返回EFBIG.
似乎OSX不支持显式open64()和pwrite64()函数.它似乎sizeof(off_t)也是一个适当的8字节大小,这意味着它pwrite()应该采用64位偏移量.是否有一个我在调用时缺少的标志open(),或者某些OSX特定的设置我应该传递给我的文件描述符fcntl()以启用大文件支持?
最后,当我检查时getrlimit(),使用该RLIMIT_FSIZE选项,它表示当前和最大文件大小限制都是9223372036854775807字节.所以这似乎并没有阻止我通过编写大文件pwrite().
有没有其他人pwrite()在64位OSX下遇到问题?
编辑:每个请求,我正在添加调用的代码pwrite()...请注意,此代码在写入线程内:
for (int i=0; i < data->iterations; i++)
{
unsigned char* ptr = data->buffer;
int temp_buff_size = data->buff_size;
int offset = i * data->buff_size;
while(temp_buff_size > 0)
{
int temp_bytes_written = pwrite(data->fd, ptr, temp_buff_size, offset);
if (temp_bytes_written >= 0)
{
temp_buff_size -= temp_bytes_written; …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 Nvidia 性能基元库来调整图像大小,但该nppiResize_8u_C3R函数抛出NPP_RESIZE_FACTOR_ERROR的错误未在文档中列出作为该函数的错误返回代码之一。这是我希望简单的代码:
#include <iostream>
#include <nppi.h>
int image_a_pitch;
NppiSize image_a_size = {.width = 960, .height = 540};
NppiRect image_a_roi = {.x = 0, .y = 0, .width = 960, .height = 540};
Npp8u* image_a = nppiMalloc_8u_C3(960, 540, &image_a_pitch);
int image_b_pitch;
NppiSize image_b_size = {.width = 960, .height = 540};
NppiRect image_b_roi = {.x = 0, .y = 0, .width = 960, .height = 540};
Npp8u* image_b = nppiMalloc_8u_C3(960, 540, &image_b_pitch);
NppStatus result = nppiResize_8u_C3R(image_a, image_a_pitch, …Run Code Online (Sandbox Code Playgroud) 我一直想知道围绕对象初始化的C++ 03规范中的语言,特别是第8.5节第9段所述,
"如果没有为对象指定初始化程序,并且该对象具有(可能是cv限定的)非POD类类型(或其数组),则该对象应默认初始化;如果该对象具有const限定类型,底层类类型应具有用户声明的默认构造函数.否则,如果没有为非静态对象指定初始化程序,则该对象及其子对象(如果有)具有不确定的初始值;如果该对象或其任何子对象是const-qualified类型,该程序是不正确的."
我想特别注意该子句,"否则,如果没有为非静态对象指定初始化器,则该对象及其子对象(如果有)具有不确定的初始值".根据第8.5节第5段,默认初始化的定义分为三种情况:
据我了解,第9段说明如果我们有一个没有初始化器的非POD类类型,那么它将被调用默认构造函数.令我困惑的是在POD类类型的情况下会发生什么......从我强调的条款看来,没有提到POD类类型需要默认的构造函数调用.然而,如果我创建了类似POD类的类型
struct POD_class
{
int a;
int b;
POD_class() { cout << "Default constructor called" << endl; }
};
int main()
{
POD_class test;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在POD_class编译和运行此代码时,似乎调用了默认构造函数g++.因此,即使POD_class没有特定的初始化程序,它似乎仍然是默认初始化的,默认初始化定义中的情况#1,因为调用了该类型的默认构造函数.
基于上述情况,这里是我的问题:对于一个POD类,并没有默认初始化一个对象作为第9段提到的非静态POD类意味着它的默认构造函数不叫,或者说,它根本就不是零初始化?