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] 元素(数组中的第 2 个)的开始指针
- 取消引用指针值
- 设置min_value等于数组中的第二个元素。
但是,我的实验似乎表明发生了一些不同的事情:
- 取消引用指针值
- 设置min_value等于数组的第一个元素
- 增加指向下一个元素的指针
有人可以澄清一下吗?
// 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.
在一般情况下,函数定义是错误的,因为 begin
和 end
指定的范围可以为空,并且 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++;
工作原理如下:
operator++
- 它增加了指针,但 return 是原来的指针。
operator*
- 取消引用之前 returned 的指针,return它指向的 T。
operator=
将左侧存储到右侧,return 存储右侧。
您没有使用最后一个 return 值,但理论上可以。
请注意,在#2 中您使用了#1 中的 return,而不是再次访问指针。
优先级只是关于如何解析代码的规则。 ++
第一,*
第二。但是当代码被执行时,你必须考虑操作符实际上做了什么.
在您的情况下,会发生以下情况:
- 复制了
begin
。
- 原来是递增的
- 副本已退回。
- 副本被取消引用。
- 副本分配给
min_value
。
这就是 post-increment 运算符的工作方式,也是您在为自己的类型重载运算符时的编写方式:
T operator++(int)
{
T copy = *this;
++(*this);
return copy;
}
实际上,在内置的post增量运算符的情况下,增量不一定非得是第2步。它也可以在稍后发生,只要因为可观察到的行为是相同的。例如,没有什么能阻止编译器在返回副本后递增原始值。当然,您不能在自己的重载运算符中执行这样的操作。
我辅导学生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] 元素(数组中的第 2 个)的开始指针
- 取消引用指针值
- 设置min_value等于数组中的第二个元素。
但是,我的实验似乎表明发生了一些不同的事情:
- 取消引用指针值
- 设置min_value等于数组的第一个元素
- 增加指向下一个元素的指针
有人可以澄清一下吗?
// 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.
在一般情况下,函数定义是错误的,因为 begin
和 end
指定的范围可以为空,并且 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++;
工作原理如下:
operator++
- 它增加了指针,但 return 是原来的指针。operator*
- 取消引用之前 returned 的指针,return它指向的 T。operator=
将左侧存储到右侧,return 存储右侧。
您没有使用最后一个 return 值,但理论上可以。
请注意,在#2 中您使用了#1 中的 return,而不是再次访问指针。
优先级只是关于如何解析代码的规则。 ++
第一,*
第二。但是当代码被执行时,你必须考虑操作符实际上做了什么.
在您的情况下,会发生以下情况:
- 复制了
begin
。 - 原来是递增的
- 副本已退回。
- 副本被取消引用。
- 副本分配给
min_value
。
这就是 post-increment 运算符的工作方式,也是您在为自己的类型重载运算符时的编写方式:
T operator++(int)
{
T copy = *this;
++(*this);
return copy;
}
实际上,在内置的post增量运算符的情况下,增量不一定非得是第2步。它也可以在稍后发生,只要因为可观察到的行为是相同的。例如,没有什么能阻止编译器在返回副本后递增原始值。当然,您不能在自己的重载运算符中执行这样的操作。