以什么顺序获取C++中全局对象的构造函数?
这个问题出现在内存池的上下文中,该内存池管理一些消费者的内存需求.我看到了一个相当大的源代码,它在全局命名空间中定义了一些消费者只使用堆函数.应添加内存池而不更改使用者的名称空间.因此,我在全局命名空间中添加了一个池类和一个定义,并修改了每个使用者类以从类"thePool"的实例中获取内存.不幸的是,在执行结束时,当调用所有全局析构函数时,我得到了一个很好的段错误.gdb backtrace显示分支到pool :: free会产生段错误.这听起来很奇怪.但是,我把它归结为一个非常简单的池/消费者示例,它位于全局命名空间中.不幸的是,这并没有重现段错误 - 池的析构函数在消费者的所有析构函数之后被调用.这是纯粹的运气,还是对g ++ 4.5的一个受过良好教育的猜测?
这里简单的例子:
#include<iostream>
using namespace std;
struct pool {
pool() {
cout << "pool::pool" << endl;
}
~pool() {
cout << "pool::~pool" << endl;
}
void get() {
cout << "pool::get" << endl;
}
void free() {
cout << "pool::free" << endl;
}
};
pool thePool;
struct consumer {
~consumer() {
cout << "consumer::~consumer" << endl;
thePool.free();
}
consumer() {
cout << "consumer::consumer" << endl;
thePool.get();
}
};
consumer a,b;
int main() …Run Code Online (Sandbox Code Playgroud) 我不得不从g ++ - 4.6切换到4.7(所以我可以使用一些C++ 11功能).现在,编译器抱怨:
In function WordJIT<float>::WordJIT(): undefined reference to JitRegType<float>::Val_t
我想知道这些编译器版本之间是否有什么变化会影响符号解析.或者在新版本(4.7)中更好地实现了语言,我正在做的是错误的:(相同的代码用4.6编译)
class Jit {
public:
enum RegType { f32=0,f64=1,u16=2,u32=3,u64=4,s16=5,s32=6,s64=7 };
// ...
};
template <class T> struct JitRegType {};
template <> struct JitRegType<float> { static const Jit::RegType Val_t = Jit::f32; };
Run Code Online (Sandbox Code Playgroud)
#include "jit.h"
template<class T>
class WordJIT
{
WordJIT() {
mapReg.insert( std::make_pair( JitRegType<T>::Val_t , jit.getRegs( JitRegType<T>::Val_t , 1 ) ) );
}
private:
typedef std::map< Jit::RegType , int > MapRegType;
mutable MapRegType mapReg;
};
Run Code Online (Sandbox Code Playgroud)
是 …
我试图在包装类中保留一个临时值,但无法弄清楚。
\n我可以在 const 引用中保存一个临时值:
\n const string& a = string("abc");\nRun Code Online (Sandbox Code Playgroud)\n但无法使用包装类来模仿这一点,例如:
\n reference_wrapper<const string> b = cref( string("abc") );\nRun Code Online (Sandbox Code Playgroud)\n\n\n错误:使用已删除的函数 \xe2\x80\x98void std::cref(const _Tp&&) [with _Tp\n= __cxx11::basic_string]\xe2\x80\x99 102 | Reference_wrapper b = cref( string("abc") );
\n
我试图避免像第一行代码那样破坏临时文件。是否可以编写一个可以保存常量引用的包装类?
\n是否可以定义一个类,它不是类模板,并且可以存储(例如在构造时)对任何特定类型的引用并稍后通过 getter 方法检索它?
struct Wrapper {
template<typename T> Wrapper(const T& t): t_(t);
// How to store the reference??
};
Run Code Online (Sandbox Code Playgroud)
Boost::variant当然不是解决方案,因为它是作为类模板实现的。而且我没有 RTTI。(在HPC环境下,性能就是一切!)
该getter()应能记住的类型。这样auto以后就可以使用了。
假设您尝试执行以下操作:
template</* args */>
typename std::enable_if< /*conditional*/ , /*type*/ >::type
static auto hope( /*args*/) -> decltype( /*return expr*/ )
{
}
Run Code Online (Sandbox Code Playgroud)
是否可以将条件包含/重载(std::enable_if)与trailing-return-type(auto ... -> decltype())结合起来?
在使用预处理器的解决方案中,我不会感兴趣.我总是可以这样做
#define RET(t) --> decltype(t) { return t; }
Run Code Online (Sandbox Code Playgroud)
并扩展它以采取整个条件.相反,如果语言支持它而不使用返回类型的其他特征,即ReturnType<A,B>::type_t函数体中使用的任何特性,我感兴趣.
如何在STL容器中存储任意数量的动态创建的实例(不同类型),以便以后只有容器可以释放内存?
它应该像这样工作:
std::vector< void * > vec;
vec.push_back( new int(10) );
vec.push_back( new float(1.) );
Run Code Online (Sandbox Code Playgroud)
现在,如果vec超出范围,则会破坏指向实例的指针,但不会释放内存int和for float.显然我做不到:
for( auto i : vec )
delete *i;
Run Code Online (Sandbox Code Playgroud)
因为void*它不是指向对象的指针类型.
您可以反对并争辩说这不是一个好主意,因为无法访问向量的元素.这是对的,我自己也不会访问它们.NVIDIA驱动程序将访问它们,因为它只需要地址(void*很好)它的内核调用参数.
我想这里的问题是它可以是存储的不同类型.想知道如果一个union人想要将这个作为参数传递给cuda内核,是否可以做到这一点.
内核接受不同类型的参数,并通过遍历表达树(表达式模板)来收集,而表达式树(表达式模板)预先不知道类型.因此,在访问叶子时,您将存储参数.它只能是void*,内置类型为int,float等.
可以在内核启动后立即删除该向量(启动是异步的,但驱动程序先复制参数然后继续主机线程).第二个问题:每个参数都向驱动程序传递一个void*.无论是int,float还是void*.所以我猜一个人可以分配比所需更多的内存.我认为联盟的东西可能值得一看.
在具有 4 个 NVIDIA GPU 的节点上,我在设备 0 上启用了 ECC 内存保护(所有其他都禁用了 ECC)。由于我在设备 0 上启用了 ECC,我的应用程序(CUDA,仅使用一个设备)在尝试在此设备 0(驱动程序 API)上创建上下文时挂起。我不知道为什么它在那一刻挂起。如果我根据另一台设备使用不同的设备设置 CUDA_VISIBLE_DEVICE 它工作正常。它必须与启用 ECC 有关。有什么想法吗?这里的输出nvidia-smi:(为什么它报告 99% 不稳定的 GPU 利用率,那里什么都没有运行?)
+------------------------------------------------------+
| NVIDIA-SMI 4.304.54 Driver Version: 304.54 |
|-------------------------------+----------------------+----------------------+
| GPU Name | Bus-Id Disp. | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
|===============================+======================+======================|
| 0 Tesla K20m | 0000:02:00.0 Off | 1 |
| N/A 29C P0 49W / 225W | 0% 12MB / 4799MB …Run Code Online (Sandbox Code Playgroud) 的unordered_map<>(C++ 11)使用一个散列函数到内部组织它的键值.碰撞概率非常小(1.f/std:numeric_limits<size_t>::max()).
是否可以使用unordered_map<>存储容器进行堆内存管理?也就是说,如果两个元素混合(通过碰撞),程序的稳定性就会被破坏.在我的情况下,将导致重复调用free()相同的指针.(SIGSEGV).
或者,碰撞概率在搜索密钥时才很重要.并且保证两个不同的键总是引用不同的值?
跟进问题:说它的unordered_map标准哈希函数不适合我的应用程序.如果想要确保不会发生冲突,并且可以将自己限制为最大size_t元素,那么可以提供自己的哈希函数来返回参数本身.就像是:
template<class T>
struct Hash
{
size_t operator()(T t) {
return (size_t)t;
}
}
Run Code Online (Sandbox Code Playgroud)
并确保没有碰撞?
类可以在不实例化的情况下公开类型.例如:
class bar {
typedef int GET_TYPE;
};
template<class T>
void foo() {
typename T::GET_TYPE t;
// do something with t
}
foo<bar>();
Run Code Online (Sandbox Code Playgroud)
可以以类似的方式公开整数吗?在某种意义上,模板参数可以是类型或内置类型.
考虑一下这段代码
template<typename T>
void call_me(const T& arg) {
}
template<int i>
struct custom_type {
};
void foo(int i)
{
switch (i) {
case 0:
call_me( custom_type<0>() );
break;
case 1:
call_me( custom_type<1>() );
break;
case 2:
call_me( custom_type<2>() );
break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
switch语句在其意图的意义上是不完整的,即对所有整数起作用,而不仅仅是上面明确提到的几个整数.C++不允许声明,custom_type<i>因为i它不是一个常量表达式.(..并且我无法将函数的参数更改foo为常量表达式).另外,我不想使用外部代码生成器生成一个巨大的switch语句并将其反馈到源代码中.
在C++/11/14/17中是否有任何方法可以以call_me优雅的方式编写函数调用,或者只是答案,"不,C++是静态类型的."?