std::reverse 在 MFC CArray 上
std::reverse on MFC CArray
我有这样一组点:
CArray<CPoint,CPoint> points;
而且我需要颠倒点的顺序。我试过这个方法:
std::reverse( &points[0], &points[0] + points.GetSize() );
并且有效。然后我尝试了另一种方法:
std::reverse( &points[0], &points[points.GetUpperBound()] );
但这不起作用:最后一项的排序不正确。为什么?
这是因为 STL 算法采用 [b, e) 形式的范围(即 e 除外),而 the function you used returns the position of the last actual last element.
还需要注意的是,你的第二种形式在数组为空的情况下问题更大。根据文档,该函数在本例中为 returns -1 。轰!
documentation表示GetUpperBound()
returns是最后一个元素的索引,所以&points[points.GetUpperBound()]
表示指向最后一个元素的迭代器,而STL算法需要half-像 [begin, end)
这样的开放范围,即 end
必须直接指向最后一个元素 .
之后的
首先,虽然 STL 的算法(包括 std::reverse()
)旨在与 STL 容器或与 STL 兼容的容器(即提供与 STL 兼容的迭代器的容器)一起正常工作,但我不确定将它们与MFC 容器.
当然,MFC 容器在设计时并未考虑到 STL 算法兼容性。
我建议将您的代码从使用 MFC 容器(如 CArray
)转移到更现代的容器(如 std::vector
)。
也就是说,在第二种情况下:
std::reverse( &points[0], &points[points.GetUpperBound()] );
您传递给 std::reverse()
的第二个 "iterator" 参数是 而不是 指向 one-past 最后一个有效项(就像 &points[0] + points.GetSize()
的第一种情况),但它实际上指向 最后一个有效项 .
事实上,CArray::GetUpperBound()
returns 最后一个有效索引(来自 MSDN 文档):
Because array indexes are zero-based, this function returns a value 1
less than GetSize
.
您可能想使用 &points[points.GetSize()]
或 &points[points.GetUpperBound() + 1]
之类的东西,但这些会失败,因为 CArray
重载 operator[]
,至少在调试中实施绑定检查构建。
使用上述这些替代方案,您最终会使用超出有效范围的索引。
但是,让我重复一遍:考虑将您的代码从 CArray
移至 std::vector
。您仍然可以将 MFC 用于应用程序的前端 GUI;但是对于 "core" 的应用程序,对于 "business logic",使用现代 C++ 和 STL 容器是更好的选择。
您可以使用堆栈反转数组 link:
#include <stack>
using namespace std;
void ReverseArray(CArray<CPoint,CPoint> points, int n)
{
// create an empty stack of integers
stack<CPoint,CPoint> stack;
// push each array element into a stack
for (int i = 0; i < n; i++) {
stack.push(points[i]);
}
// start from index 0
int index = 0;
// pop values from the stack until it becomes empty
while (!stack.empty())
{
// assign each popped item back to the original array
points[index++] = stack.top();
stack.pop();
}
}
我有这样一组点:
CArray<CPoint,CPoint> points;
而且我需要颠倒点的顺序。我试过这个方法:
std::reverse( &points[0], &points[0] + points.GetSize() );
并且有效。然后我尝试了另一种方法:
std::reverse( &points[0], &points[points.GetUpperBound()] );
但这不起作用:最后一项的排序不正确。为什么?
这是因为 STL 算法采用 [b, e) 形式的范围(即 e 除外),而 the function you used returns the position of the last actual last element.
还需要注意的是,你的第二种形式在数组为空的情况下问题更大。根据文档,该函数在本例中为 returns -1 。轰!
documentation表示GetUpperBound()
returns是最后一个元素的索引,所以&points[points.GetUpperBound()]
表示指向最后一个元素的迭代器,而STL算法需要half-像 [begin, end)
这样的开放范围,即 end
必须直接指向最后一个元素 .
首先,虽然 STL 的算法(包括 std::reverse()
)旨在与 STL 容器或与 STL 兼容的容器(即提供与 STL 兼容的迭代器的容器)一起正常工作,但我不确定将它们与MFC 容器.
当然,MFC 容器在设计时并未考虑到 STL 算法兼容性。
我建议将您的代码从使用 MFC 容器(如 CArray
)转移到更现代的容器(如 std::vector
)。
也就是说,在第二种情况下:
std::reverse( &points[0], &points[points.GetUpperBound()] );
您传递给 std::reverse()
的第二个 "iterator" 参数是 而不是 指向 one-past 最后一个有效项(就像 &points[0] + points.GetSize()
的第一种情况),但它实际上指向 最后一个有效项 .
事实上,CArray::GetUpperBound()
returns 最后一个有效索引(来自 MSDN 文档):
Because array indexes are zero-based, this function returns a value 1 less than
GetSize
.
您可能想使用 &points[points.GetSize()]
或 &points[points.GetUpperBound() + 1]
之类的东西,但这些会失败,因为 CArray
重载 operator[]
,至少在调试中实施绑定检查构建。
使用上述这些替代方案,您最终会使用超出有效范围的索引。
但是,让我重复一遍:考虑将您的代码从 CArray
移至 std::vector
。您仍然可以将 MFC 用于应用程序的前端 GUI;但是对于 "core" 的应用程序,对于 "business logic",使用现代 C++ 和 STL 容器是更好的选择。
您可以使用堆栈反转数组 link:
#include <stack>
using namespace std;
void ReverseArray(CArray<CPoint,CPoint> points, int n)
{
// create an empty stack of integers
stack<CPoint,CPoint> stack;
// push each array element into a stack
for (int i = 0; i < n; i++) {
stack.push(points[i]);
}
// start from index 0
int index = 0;
// pop values from the stack until it becomes empty
while (!stack.empty())
{
// assign each popped item back to the original array
points[index++] = stack.top();
stack.pop();
}
}