【问题标题】:Why shouldn't we use pointer arithmetic with gsl::not_null?为什么我们不应该对 gsl::not_null 使用指针运算?
【发布时间】:2016-07-01 01:17:58
【问题描述】:

这是一个人为的例子,但请考虑以下几点:

#include <iostream>
#include "gsl.h"

int main(){

  //object or array that I'd like to iterate over one byte at a time
  char array[] = {'a','b','c','d','e','f'};

  //create a C-like iterator
  char* it = &array[0];

  //use pointer arithmetic to process
  std::cout << *it << std::endl; it++;
  std::cout << *it << std::endl; it++;
  std::cout << *it << std::endl; it++;
}

为了安全起见,我想用not_null标记指针。
但是,编译失败。

#include "gsl.h"
#include <iostream>

int main(){

  //object or array that I'd like to iterate over one byte at a time
  char array[] = {'a','b','c','d','e','f'};

  //create a C-like iterator
  gsl::not_null<char*> it = &array[0];

  //use pointer arithmetic to process
  std::cout << *it << std::endl; it++;
  std::cout << *it << std::endl; it++;
  std::cout << *it << std::endl; it++;
}

not_null 的类除外:

// unwanted operators...pointers only point to single objects!
// TODO ensure all arithmetic ops on this type are unavailable
not_null<T>& operator++() = delete;
not_null<T>& operator--() = delete;
not_null<T> operator++(int) = delete;
not_null<T> operator--(int) = delete;
not_null<T>& operator+(size_t) = delete;
not_null<T>& operator+=(size_t) = delete;
not_null<T>& operator-(size_t) = delete;
not_null<T>& operator-=(size_t) = delete;

我对他们为什么这样做感到困惑。
为什么我不能有一个改变其值的指针?

尤其是在交通便利的情况下:

it = &array[0];
it = static_cast<char*>(it)+1;

我错过了not_null 的要点吗?
C++ Guidelines 没有说明为什么这样的事情会是一个糟糕的用例。

【问题讨论】:

  • 大概not_null 用于在任何情况下都不能为空的单个对象。可以编译时检查它们最初是否为空,但如果允许指针算术,则不能保证它们永远不会为空。所以他们不允许指针算术,并且在这个过程中引入了一个新的保证,即指针只能被重新分配;演员在这里作弊(重新引入 null 的可能性),但就这样吧。
  • 你不应该在 C++ 中使用 c 成语,我就这么说吧。如果您想使用 ++ 对它们进行操作,请坚持使用普通的 char * 数组/指针
  • @self:我认为 C++ 中的迭代器协议是指针算法的形式化和泛化,它并不是 C 特有的。
  • 指南可能更希望您为数组构造一个gsl::span,然后使用其中的迭代器。

标签: c++ pointers null pointer-arithmetic cpp-core-guidelines


【解决方案1】:

这是不允许的,因为指针不是数组。是的,一个数组可以衰减成一个指针,但正如这个词所暗示的那样,这种衰减会丢失信息。结果指针不等价于数组。

相比之下,将数组转换为gsl::span 不会丢失任何信息。数组的大小和遍历它的能力都保持不变。

not_null 是指向对象的指针,而不是对象数组。正如unique_ptrshared_ptr 不允许指针算术一样。如果要使用指针算法处理数组,正确答案是gsl::span 及其迭代器。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-12
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    相关资源
    最近更新 更多