假设我有一堂课:
class A
{
private:
const int * const v;
public:
A();
}
我想v在初始化列表中分配,我想我可以定义如下构造函数:
A::A():v((int*)malloc(10*sizeof(int))){}
但是,v 必须以非标准方式分配,如下所示:
cudaMalloc(&v,10*sizeof(int));
注意cudaMalloc是用于分配 GPU 内存的 CUDA API。
假设我有一堂课:
class A
{
private:
const int * const v;
public:
A();
}
我想v在初始化列表中分配,我想我可以定义如下构造函数:
A::A():v((int*)malloc(10*sizeof(int))){}
但是,v 必须以非标准方式分配,如下所示:
cudaMalloc(&v,10*sizeof(int));
注意cudaMalloc是用于分配 GPU 内存的 CUDA API。
(忽略整体设计、异常安全等大局问题,只关注最狭窄范围内的问题)
放弃在初始化列表中做的想法,而是在构造函数体中做
A::A() : v(NULL)
{
cudaMalloc(&v, 10 * sizeof(int));
}
或者,或者,将分配函数包装到您自己的返回指针的函数中
void *wrapped_cudaMalloc(size_t size)
{
void *m = NULL;
cudaMalloc(&m, size);
return m;
}
...
A::A() : v(wrapped_cudaMalloc(10 * sizeof(int)))
{}
只是为了完整起见,在初始化列表中还有一种丑陋的复杂方式来完成它,而无需通过利用,operator的属性来创建任何包装器
A::A() : v((cudaMalloc(&v, 10 * sizeof(int)), v))
{}
注意逗号表达式周围的附加对(),这是满足初始化语法所必需的(否则,将被视为参数分隔符而不是逗号运算符)。
除了 AndreyT 的出色帖子(以及他对逗号运算符的创造性使用)之外,您还可以这样总结:
class cudaMallocedInt
{
private:
int *v;
public:
cudaMallocedInt(int n)
{
cudaMalloc(&v, n * sizeof(int));
}
cudaMallocedInt(const cudaMallocedInt &o)
{
// Do whatever is appropriate here. Probably some sort of dance.
}
~cudaMallocedInt()
{
// Remember to cudaFree or whatever
}
operator int*()
{
return v;
}
};
class A
{
private:
cudaMallocedInt v;
public:
A()
: v(10)
{
}
...
};
更新:正如Johnsyweb在评论中指出的那样,请务必遵守三原则,以确保事情不会顺利进行,并且您会浪费您的周末来努力调试错误,而不是享受乐趣!