C ++中递增和解除引用指针的顺序

时间:2015-07-25 08:47:10

标签: c++ arrays pointers

我用C ++教学生,最近遇到了一个涉及指针算法和数组名称的问题。我感到困惑的主要是声明

T min_value = *begin++; 

Cplusplus告诉我++运算符的优先级高于* dereference运算符,所以我假设begin首先递增然后解除引用。此外,this站点确认当您将数组的名称传递给函数时,它将变为指向第一个元素的地址的指针,元素[0]。但是,当我在Visual Studio中运行下面的代码时,看起来min_value在开始时设置为1.5,这似乎与我认为的操作顺序相矛盾。

我认为应该是:

  1. 将开始指针递增到[1]元素(数组中的第2个)
  2. 取消引用指针值
  3. 将min_value设置为等于数组中的第2个元素。
  4. 然而,我的实验似乎表明发生了不同的事情:

    1. 取消引用指针值
    2. 将min_value设置为等于数组的第1个元素
    3. 增加指向下一个元素的指针
    4. 有人可以澄清一下吗?

      // Problem #3: Please write the implementation of min() function and max() function..
      
      #include <iostream> 
      using namespace std; 
      template<typename T> 
      
      T min(T* begin, T* end) 
      { 
              T min_value = *begin++; 
              while(begin != end) // You can use for-loop too. 
              { 
                      if( *begin < min_value) 
                              min_value = *begin; 
                      begin++; 
              } 
              return min_value; 
      } 
      template<typename T> 
      T max(T* begin, T* end) 
      { 
              T max_value = *begin++; 
              while(begin != end) 
              { 
                      if( *begin > max_value) 
                              max_value = *begin; 
                      begin++; 
              } 
              return max_value; 
      } 
      int main() 
      { 
              double arr[] = {    1.5, 4.5, 3.5, 2.5, 5.5 }; 
              int values[] = {    1, 2, 3, 4, -1, 5 }; 
              cout << "min of arr[] is : " << min(arr, arr + 5) << endl; 
              cout << "min of values[] is : " << min(values, values + 6) << endl; 
              cout << "max of arr[] is : " << max(arr, arr + 5) << endl; 
              cout << "max of values[] is : " << max(values, values + 6) << endl; 
      }
      

3 个答案:

答案 0 :(得分:2)

优先级只是解析代码的规则。 ++排在第一位,*排在第二位。但是当代码执行时,你必须考虑操作符实际上做什么

在您的情况下,会发生以下情况:

  1. 制作了begin的副本。
  2. 原件增加。
  3. 返回副本。
  4. 副本已取消引用
  5. 副本已分配给min_value
  6. 这就是后增量运算符的工作原理,以及在为自己的类型重载运算符时如何编写运算符:

    T operator++(int)
    {
        T copy = *this;
        ++(*this);
        return copy;
    }
    

    实际上,在内置后增量运算符的情况下,增量不一定必须是步骤2.只要可观察行为相同,它也可能在稍后发生。例如,没有什么能阻止编译器在返回副本后递增原始值。当然,你无法在自己的重载运算符中执行这样的操作。

答案 1 :(得分:1)

此表达式

T min_value = *begin++; 

可以通过以下方式想象

auto temp = begin;
T min_value = *temp;
++begin;

根据C ++标准(5.2.6增量和减量)

  

1后缀++表达式的值其值   操作数即可。 [注意:获得的值是原始值的副本   -end note] ...对++表达式的值计算进行排序   在修改操作数对象之前。

一般情况下,函数定义是错误的,因为beginend指定的范围可以为空,并且begin可以指向有效范围之外。在这种情况下,你既不会增加开始也不会取消引用它。

因此,以下列方式编写

更为正确
T * min( T* begin, T* end ) 
{
    T *min_value = begin;

    if ( begin != end )
    {
        while( ++begin != end )
        { 
            if( *begin < *min_value ) min_value = begin; 
        } 
    }

    return min_value; 
} 

在这种情况下,函数的调用将类似于

cout << "min of arr[] is : " << *min(arr, arr + 5) << endl;
                               ^^^

答案 2 :(得分:1)

您不应混淆运营商的返回值和优先级。

第一个是处理操作员返回的内容,第二个是处理发生的事情。

所以如果你有:

T min_value = *begin++;

以下是它的工作原理:

  1. operator++ - 它递增指针,但返回原来的指针。
  2. operator* - 取消引用先前返回的指针,返回它指向的T。
  3. operator=将左侧存放到右侧,返回右侧。
  4. 你没有使用最后一个返回值,但理论上你可以。

    请注意,在#2中,您使用#1的返回,而不是再次访问指针。