C++技巧之不透明指针

在阅读头文件时,经常会发现如下类似的代码。当你想要查找具体的结构体定义,发现没有任何地方出现了该定义。你甚至会怀疑自己的头文件是否齐全。

struct nvgraphContext;
typedef struct nvgraphContext *nvgraphHandle_t;

typedef struct CUstream_st *CUstream; 
typedef __device_builtin__ struct CUstream_st *cudaStream_t;

这种称为不透明指针,一般出现在闭源代码中,用于隐藏结构体的具体定义。是一种特别常用的技巧。

使用场景

假设有头文件 header.cpp 中有如下定义:

struct context;
typedef struct context* context_t;

如果将不透明指针以指针使用时,不需要提供定义

void setContext(context_t ctx, context_t ctx2) {
  ctx = ctx2;
}

为什么这样的场景不会出错?一般在编译器生成代码的时候,需要知道结构体的大小,但是如果我们在使用过程中,不访问其内部变量,就可以将 context_t 作为一个void *使用,void* 就是一个不完整类型(incomplete type),void* 的大小是固定的,编译器就能够正常处理。

注意,如果按照如下方式,声明一个栈变量,是会报错的。

    context ctx;

是因为,此时编译器需要知道 context的大小,但是context此时是不完整类型,大小是未知的。

如果需要通过不透明指针访问内部变量时,需要提供定义

struct context {
  int length;
};

void setLength(context_t ctx, int len) {
  ctx->length = len;
}

int main() {
  context_t ctx = new context;
  setLength(ctx, 10);
  return 0;
}

如果此时不提供结构体的具体定义时,就会出现如下错误:

error: invalid use of incomplete type ‘struct context’
   12 |   ctx->length = len;

你可能感兴趣的:(c++,c++,不透明指针)