3

我正在使用一个 API,其中调用者传入一个指向东西的指针数组,以及数组的长度。为了使我的代码更具可读性/可维护性,我希望能够有效地为每个参数命名,而不是将它们称为arg[0],arg[1]等。即使声明对所有可能参数的引用是否安全由于可选参数,传入的数组可以是不同的大小?

我正在尝试做这样的事情:

void myFunc(int out_args[], size_t nargs) {
  int &foo = out_args[0];
  int &bar = out_args[1];    // bar is optional argument. is this safe?
  ...
  foo = 5;
  if(2 >= nargs)
    bar = 10;
  ...
}

请注意,参数是输出参数,所以我真的很想引用它们。那么,如果我从未真正使用它,那么对 args[1] 进行悬空引用是否安全?

我的猜测是这是安全的,因为我认为引用的实现方式是&在引用的变量声明中将其视为* const,并且每当我使用引用时,编译器都会自动为我取消引用指针。即,在引擎盖下,我想我写的东西被翻译成类似的东西

void myFunc(int out_args[], size_t nargs) {
  int *const foo = &out_args[0];
  int *const bar = &out_args[1];    // bar is optional argument. is this safe?
  ...
  *foo = 5;
  if(2 >= nargs)
    *bar = 10;
  ...
}

在这种情况下,我相信代码实际上不会访问它不应该访问的内存,所以如果上面的版本相当于这个,那么我应该没问题,对吧?


编辑:我基本上是在编写一个插件,而我正在使用并且无能为力的 API 可以使用类似的东西调用我的代码

int ret_vals[1];     // only care about 1 return value
myFunc(ret_vals, 1);

或者

int ret_vals[2];     // care about both return values
myFunc(ret_vals, 2);

甚至

myFunc(NULL, 0);     // ignore all return values; just marvel at the side effects

我的代码需要在所有情况下都能正常工作。

4

2 回答 2

3

args[1]如果args不是指向至少两个元素的数组的第一个元素的指针,则评估表达式是未定义的行为。立即获取地址,如&args[1],仅当args指向至少一个元素的数组的第一个元素时才有效。

基本上,不要这样做。

于 2013-10-23T23:32:25.390 回答
1

那么,如果我从未真正使用它,那么对 args[1] 进行悬空引用是否安全?

该标准规定引用应绑定到第 8.3.2 节中的有效对象:

不应有对引用的引用,没有引用数组,也没有指向引用的指针。[...] 应初始化引用以引用有效的对象或函数。[注意:特别是,空引用不能存在于定义良好的程序中,因为创建此类引用的唯一方法是将其绑定到通过取消引用空指针获得的“对象”,这会导致未定义的行为。[...] — 结束注 ]

这意味着它不安全

我的猜测是这是安全的,因为我想象引用的实现方式是将引用的变量声明中的 & 视为 * const,并且每当我使用引用时,编译器都会自动为我取消引用指针。

不,不要那样做。同样,该标准没有指定如何实现引用。事实上,在第 8.3.2 节中它指出:

未指定引用是否需要存储。

至于您的代码:一旦确定参数存在,您就可以命名参数。

void myFunc(int out_args[], size_t nargs) {
  int &foo = out_args[0];
  ...
  foo = 5;
  if(nargs >= 2) {
    int &bar = out_args[1];
    bar = 10;
  }
  ...
}

我觉得有义务让您注意到不鼓励在 C++ 中使用 C 样式的数组。std::vector使用orstd::array代替通常是一个好主意。

于 2013-10-24T01:43:03.803 回答