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



我指导学生学习c++,最近遇到了一个涉及数组名称的指针算术问题。我最困惑的是语句

T min_value = *begin++; 

Cplusplus告诉我++操作符比*解引用操作符具有更高的优先级,因此我假设首先对begin进行加1操作,然后再对其解引用。此外,本站点还确认,当将数组的名称传递给函数时,它会被转换为指向第一个元素element[0]地址的指针。然而,当我在Visual Studio中运行下面的代码时,看起来min_value在开始时被设置为1.5,这似乎与我认为的操作顺序相矛盾。

我认为应该是:

  1. 增加指向[1]元素(数组中的第二个元素)的begin指针
  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; 
}

优先级只是如何解析代码的规则。第一是++,第二是*。但是在执行代码时,必须考虑操作符的实际作用

在你的例子中,会发生以下情况:

  1. 复制begin文件
  2. 原值递增
  3. 副本返回。
  4. 副本被解引用
  5. 副本分配给min_value

这就是后自增操作符的工作方式,当您为自己的类型重载操作符时,也是这样编写操作符的:

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

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

这个表达式

T min_value = *begin++; 

可以这样想象

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

根据c++标准(5.2.6自增和自减)

1后缀++表达式的值 its的值操作数。[注:获取的值为原始值的副本。-结束提示]…对++表达式的值计算进行排序

在一般情况下,函数定义是错误的,因为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;
                               ^^^

不要混淆操作符的返回值和优先级。

第一个语句处理操作符返回的内容,第二个语句处理发生的时间。

所以如果你有:

T min_value = *begin++;

下面是它的工作原理:

  1. operator++ -它增加指针,但返回原来的指针。
  2. operator* -对先前返回的指针解引用,返回它指向的T。
  3. operator=将左侧存储到右侧,返回右侧。

不使用最后一个返回值,但理论上可以。

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

最新更新