为什么我们不应该使用 gsl::not_null 的指针运算?
Why shouldn't we use pointer arithmetic with gsl::not_null?
这是一个人为的例子,但请考虑以下几点:
#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
的 class 除外:
// 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 没有说明为什么这样的用例会很糟糕。
不允许,因为指针不是数组。是的,一个数组可以衰减 成一个指针,但顾名思义,这种衰减会丢失信息。结果指针不等同于数组。
相比之下,将数组转换为 gsl::span
不会丢失任何信息。数组的大小保持不变,循环访问它的能力也是如此。
not_null
用于指向对象的指针,而不是对象数组。正如 unique_ptr
和 shared_ptr
不允许指针运算一样。如果要使用指针运算来处理数组,正确答案是gsl::span
及其迭代器
这是一个人为的例子,但请考虑以下几点:
#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
的 class 除外:
// 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 没有说明为什么这样的用例会很糟糕。
不允许,因为指针不是数组。是的,一个数组可以衰减 成一个指针,但顾名思义,这种衰减会丢失信息。结果指针不等同于数组。
相比之下,将数组转换为 gsl::span
不会丢失任何信息。数组的大小保持不变,循环访问它的能力也是如此。
not_null
用于指向对象的指针,而不是对象数组。正如 unique_ptr
和 shared_ptr
不允许指针运算一样。如果要使用指针运算来处理数组,正确答案是gsl::span
及其迭代器