C ++中递增和取消引用指针的顺序

Order of incrementing and dereferencing pointer in C++

我辅导学生C++,最近遇到一个涉及数组名的指针运算的问题。我最困惑的是声明

T min_value = *begin++; 

Cplusplus tells me that the ++ operator has higher precedence than the * dereference operator, so I assume that begin is first incremented and then dereferenced. Also, this 网站证实,当您将数组名称传递给函数时,它会变成指向第一个元素(元素 [0])地址的指针。但是,当我运行下面Visual Studio中的代码时,看起来min_value一开始就设置为1.5,这似乎与我认为的操作顺序相矛盾。

我觉得应该是:

  1. 增加指向 [1] 元素(数组中的第 2 个)的开始指针
  2. 取消引用指针值
  3. 设置min_value等于数组中的第二个元素。

但是,我的实验似乎表明发生了一些不同的事情:

  1. 取消引用指针值
  2. 设置min_value等于数组的第一个元素
  3. 增加指向下一个元素的指针

有人可以澄清一下吗?

// 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; 
}

这个表达式

T min_value = *begin++; 

可以想象成下面这样

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

根据C++标准(5.2.6自增自减)

1 The value of a postfix ++ expression is the value of its operand. [ Note: the value obtained is a copy of the original value —end note ] ...The value computation of the ++ expression is sequenced before the modification of the operand object.

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

所以写成下面这样的例子会更正确

template <typename T>
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;
                               ^^^

您不应混淆运算符的 return 值和优先级。

第一个是处理运算符 return 的内容,第二个是处理什么时候发生的事情。

所以如果你有:

T min_value = *begin++;

工作原理如下:

  1. operator++ - 它增加了指针,但 return 是原来的指针。
  2. operator* - 取消引用之前 returned 的指针,return它指向的 T。
  3. operator= 将左侧存储到右侧,return 存储右侧。

您没有使用最后一个 return 值,但理论上可以。

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

优先级只是关于如何解析代码的规则。 ++ 第一,* 第二。但是当代码被执行时,你必须考虑操作符实际上做了什么.

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

  1. 复制了 begin
  2. 原来是递增的
  3. 副本已退回。
  4. 副本被取消引用
  5. 副本分配给min_value

这就是 post-increment 运算符的工作方式,也是您在为自己的类型重载运算符时的编写方式:

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

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