使用一个元素处理单个对象(如数组),使用一个过去结束指针 [英] Treating a single object like an array with one element, taking one-past-end pointer

查看:123
本文介绍了使用一个元素处理单个对象(如数组),使用一个过去结束指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

前导:众所周知,将指针移动到数组末尾是合法且明确的:

  int main()
{
int na [1] = {};
const int * naBegin = na;
const int * naEnd = na + 1; // one-past-end,OK
}

此指针可用于比较,这有助于C风格数组(或更准确地说,其中的指针)与标准库例程相兼容,例如 copy Live Demo ):

  template< typename字段,类型名Iter> 
void foo(Iter begin,Iter end)
{
std :: copy(begin,end,std :: ostream_iterator< Field>(std :: cout,std :: endl) ;
}
int main()
{
int na [1] = {};
foo< int>(na,na + 1);
}

这是合法性和定义支持的标准):



5.7添加运算符




类型被添加到指针中或从指针中减去
,结果具有指针操作数的类型如果
指针操作数指向数组对象的一个​​元素,数组
是大的足够,结果指向从
原始元素偏移一个元素,使得
的下标与原始数组元素的差异等于整数表达式
换句话说,如果表达式P指向
数组对象的第i个元素,表达式(P)+ N(等效地,N +(P))和(P)-N
(其中N具有值n )分别指向数组对象的第i + n和
i-n个元素,前提是它们存在。此外,如果
表达式P指向数组对象的最后一个元素,
表达式(P)+1指向一个超出数组对象的最后一个元素
和如果表达式Q指向一个超过数组
对象的最后一个元素,则表达式(Q)-1指向数组
对象的最后一个元素。
如果指针操作数和结果指向相同数组对象的元素
,或者一个超过数组
对象的最后一个元素,则评估不会产生溢出;


当我在标准中查看过去的vlaidity的引用时,结束指针,我发现的每个参考是讨论数组。如果我们试图把一个对象的地址,而不是一个数组的过去的结束?

一个数组,就好像它是一个数组,并获取所述对象的有效一个过去的地址。



例如=http://ideone.com/FxBsuq =nofollow>现场演示):

  #include< cstdlib> 
#include< iostream>
#include< iomanip>
#include
template< typename Field,typename Iter>
void foo(Iter begin,Iter end)
{
std :: copy(begin,end,std :: ostream_iterator< Field>(std :: cout,\\\
));
}
int main()
{
int na = 42;
foo< int> (& na,& na + 1);
}

这个代码是否合法,

解决方案

答案在于您所引用的段落之前的段落:



< blockquote>

4 /对于这些操作符,指向非数组对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,对象的类型为其元素类型。


(注意:我引用C ++ 11,因为我没有C ++ 03。 )



是的,& na + 1 是一个有效的过去 - 结束指针。


Preamble: It is well-known that taking the pointer one past the end of an array is legal and well-defined:

int main()
{
  int na [1] = {};
  const int* naBegin = na;
  const int* naEnd = na + 1; // one-past-end, OK  
}

This pointer can be used in comparisons, which contributes to C-style arrays (or, more accurately, pointers therein) being compatible with Standard Library routines which take iterators, such as copy (Live Demo):

template <typename Field, typename Iter>
void foo(Iter begin, Iter end)
{
  std::copy (begin, end, std::ostream_iterator <Field> (std::cout, std::endl);
}
int main()
{
  int na [1] = {};
  foo <int> (na, na + 1);
}

The legality and definedness of this is supported by the Standard (C++03 reference):

5.7 Additive operators

5/When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i–n-th elements of the array object, provided they exist. Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

When I've looked in the Standard for references to the vlaidity of past-the-end pointers, every reference I've found is discussing arrays. What if we were to try to take past-the-end the address of an object, not an array?


Question: Is it possible to treat a single object, not allocated as an array, as if it were an array and take a valid one-past-the-end address of said object?

For instance (Live Demo):

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <iterator>

template <typename Field, typename Iter>
void foo(Iter begin, Iter end)
{
  std::copy (begin, end, std::ostream_iterator <Field> (std::cout, "\n"));
}
int main()
{
  int na = 42;
  foo <int> (&na, &na + 1);
}

Is this code legal and well-defined by the Standard?

解决方案

The answer is in the paragraph before the one you quote:

4/ For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

(Note: I'm quoting C++11 as I don't have C++03 to hand. I'm fairly sure nothing has changed.)

So yes, &na + 1 is a valid past-the-end pointer.

这篇关于使用一个元素处理单个对象(如数组),使用一个过去结束指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆