为什么迭代器没有被取消引用为左值
Why iterator is not dereferenced as an lvalue
如果我的问题没有包含所有相关信息,我们深表歉意。请评论,我会相应地修改。
我在带有 MinGW 和 gcc 的 Win7 上使用 CLion
我一直在试验循环缓冲区并遇到了 boost::circular_buffer
,但对于我的项目的大小,我想使用 Pete Goodlife 的 circular buffer,这似乎是一个可靠的实现.hpp
。
注意:由于Boost dependencies and bcp,我知道如何减少增强依赖性。
但是,Pete 实施的以下示例未按预期运行,即 std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
的结果为 empty。我想了解原因并可能纠正其行为。
关注 MWE:
#include "circular.h"
#include <iostream>
#include <algorithm>
typedef circular_buffer<int> cbuf_type;
void print_cbuf_contents(cbuf_type &cbuf){
std::cout << "Printing cbuf size("
<<cbuf.size()<<"/"<<cbuf.capacity()<<") contents...\n";
for (size_t n = 0; n < cbuf.size(); ++n)
std::cout << " " << n << ": " << cbuf[n] << "\n";
if (!cbuf.empty()) {
std::cout << " front()=" << cbuf.front()
<< ", back()=" << cbuf.back() << "\n";
} else {
std::cout << " empty\n";
}
}
int main()
{
cbuf_type cbuf(5);
for (int n = 0; n < 3; ++n) cbuf.push_back(n);
print_cbuf_contents(cbuf);
cbuf_type df(5);
std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
print_cbuf_contents(df);
}
打印以下内容:
Printing cbuf size(3/5) contents...
0: 0
1: 1
2: 2
front()=0, back()=2
Printing cbuf size(0/5) contents...
empty
不幸的是,作为 c++ 的新手,我不明白为什么 df.begin()
迭代器没有被解引用为左值。
我怀疑罪魁祸首是(或者不完全理解)Pete 的第 72 行 circular_buffer_iterator
的成员调用 circular.h
:
elem_type &operator*() { return (*buf_)[pos_]; }
非常感谢任何帮助。
std::adjacent_difference
写入结果迭代器。在您的情况下,结果迭代器指向 df
,其大小为 0,容量为 5。这些写入将进入 df
、 的保留内存,但不会更改容器的大小,因此大小仍为 0,保留容器的前 3 个整数 space 将有您的差异。为了查看结果,被写入的容器必须已经在被写入的槽中存储了数据。
所以要看到结果你必须先将数据放入循环缓冲区中,然后将容器调整到合适的大小(基于adjacent_difference
.
返回的迭代器)
您作为输出迭代器传递的迭代器被取消引用并被视为左值,您期望的数据很可能实际上存储在循环缓冲区的缓冲区中。
问题是,除了实际的存储缓冲区外,大多数容器还包含一些必须维护的内部簿记状态。 (例如:缓冲区中有多少元素,剩余多少 space 等)。
取消引用和递增容器不会更新内部状态,因此容器不会"know"添加新数据。
考虑以下代码:
std::vector<int> v;
v.reserve(3);
auto i = v.begin();
*(i++) = 1; // this simply writes to memory
*(i++) = 2; // but doesn't update the internal
*(i++) = 3; // state of the vector
assert(v.size() == 0); // so the vector still "thinks" it's empty
使用 push_back 将按预期工作:
std::vector<int> v;
v.reserve(3);
v.push_back(1); // adds to the storage AND updates internal state
v.push_back(2);
v.push_back(3);
assert(v.size() == 3); // so the vector "knows" it has 3 elements
在您的情况下,您应该使用 std::back_inserter,这是一个迭代器,每次取消引用时都会在容器上调用 "push_back":
std::adjacent_difference(
cbuf.begin(), cbuf.end(),
std::back_inserter(df));
如果我的问题没有包含所有相关信息,我们深表歉意。请评论,我会相应地修改。
我在带有 MinGW 和 gcc 的 Win7 上使用 CLion
我一直在试验循环缓冲区并遇到了 boost::circular_buffer
,但对于我的项目的大小,我想使用 Pete Goodlife 的 circular buffer,这似乎是一个可靠的实现.hpp
。
注意:由于Boost dependencies and bcp,我知道如何减少增强依赖性。
但是,Pete 实施的以下示例未按预期运行,即 std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
的结果为 empty。我想了解原因并可能纠正其行为。
关注 MWE:
#include "circular.h"
#include <iostream>
#include <algorithm>
typedef circular_buffer<int> cbuf_type;
void print_cbuf_contents(cbuf_type &cbuf){
std::cout << "Printing cbuf size("
<<cbuf.size()<<"/"<<cbuf.capacity()<<") contents...\n";
for (size_t n = 0; n < cbuf.size(); ++n)
std::cout << " " << n << ": " << cbuf[n] << "\n";
if (!cbuf.empty()) {
std::cout << " front()=" << cbuf.front()
<< ", back()=" << cbuf.back() << "\n";
} else {
std::cout << " empty\n";
}
}
int main()
{
cbuf_type cbuf(5);
for (int n = 0; n < 3; ++n) cbuf.push_back(n);
print_cbuf_contents(cbuf);
cbuf_type df(5);
std::adjacent_difference(cbuf.begin(),cbuf.end(),df.begin());
print_cbuf_contents(df);
}
打印以下内容:
Printing cbuf size(3/5) contents...
0: 0
1: 1
2: 2
front()=0, back()=2
Printing cbuf size(0/5) contents...
empty
不幸的是,作为 c++ 的新手,我不明白为什么 df.begin()
迭代器没有被解引用为左值。
我怀疑罪魁祸首是(或者不完全理解)Pete 的第 72 行 circular_buffer_iterator
的成员调用 circular.h
:
elem_type &operator*() { return (*buf_)[pos_]; }
非常感谢任何帮助。
std::adjacent_difference
写入结果迭代器。在您的情况下,结果迭代器指向 df
,其大小为 0,容量为 5。这些写入将进入 df
、 的保留内存,但不会更改容器的大小,因此大小仍为 0,保留容器的前 3 个整数 space 将有您的差异。为了查看结果,被写入的容器必须已经在被写入的槽中存储了数据。
所以要看到结果你必须先将数据放入循环缓冲区中,然后将容器调整到合适的大小(基于adjacent_difference
.
您作为输出迭代器传递的迭代器被取消引用并被视为左值,您期望的数据很可能实际上存储在循环缓冲区的缓冲区中。
问题是,除了实际的存储缓冲区外,大多数容器还包含一些必须维护的内部簿记状态。 (例如:缓冲区中有多少元素,剩余多少 space 等)。
取消引用和递增容器不会更新内部状态,因此容器不会"know"添加新数据。
考虑以下代码:
std::vector<int> v;
v.reserve(3);
auto i = v.begin();
*(i++) = 1; // this simply writes to memory
*(i++) = 2; // but doesn't update the internal
*(i++) = 3; // state of the vector
assert(v.size() == 0); // so the vector still "thinks" it's empty
使用 push_back 将按预期工作:
std::vector<int> v;
v.reserve(3);
v.push_back(1); // adds to the storage AND updates internal state
v.push_back(2);
v.push_back(3);
assert(v.size() == 3); // so the vector "knows" it has 3 elements
在您的情况下,您应该使用 std::back_inserter,这是一个迭代器,每次取消引用时都会在容器上调用 "push_back":
std::adjacent_difference(
cbuf.begin(), cbuf.end(),
std::back_inserter(df));