我正在学习C++迭代器。我有一个奇怪的bug,当我试图从迭代器中获取一个结构的成员时,我得到了错误的数字。经过大量的尝试和错误,我发现是printf在输入结构成员时打印出了错误的数字。
以下代码给出了正确的结果:
int n_payload = cl_custom_iterator.get_payload();
std::cout << "get_payload: " << n_payload << "\n";
此代码给出错误的结果:
int n_payload = cl_custom_iterator.get_payload();
My_class::Node st_node = cl_custom_iterator.get_node();
printf("%p | get_payload: %d | get_node.n_payload: %d\n", cl_custom_iterator, n_payload, st_node.n_payload);
这是重现问题的最小示例:
#include <iostream>
#include <cstdio>
#include <vector>
class My_class
{
public:
//Troublemaker?
struct Node
{
int n_payload;
};
//Constructor
My_class(void)
{
Node st_node;
for (int cnt = 0; cnt < 5; cnt++)
{
st_node.n_payload = 33+cnt;
gast_my_array.push_back( st_node );
std::cout << "Push " << cnt << " | Payload: " << gast_my_array[cnt].n_payload << "\n";
}
}
template <typename T>
class iterator
{
public:
//! @brief constructor for the custom iterator
iterator(std::vector<T>& ira_parent_vector, size_t in_starting_index = 0) :
gra_vector(ira_parent_vector),
gu32_index(in_starting_index)
{
//Do nothing
return;
}
iterator<T>& operator++()
{
gu32_index++;
return *this;
}
iterator<T> operator++(int)
{
iterator<T> tmp(*this);
gu32_index++;
return tmp;
}
T &operator &(void)
{
return &gra_vector[gu32_index];
}
int get_payload( void )
{
return gra_vector[gu32_index].n_payload;
}
T get_node( void )
{
return gra_vector[gu32_index];
}
bool operator==(const iterator<T>& icl_rhs_iterator) const
{
return gu32_index == icl_rhs_iterator.gu32_index;
}
bool operator!=(const iterator<T>& icl_rhs_iterator) const
{
return gu32_index != icl_rhs_iterator.gu32_index;
}
private:
std::vector<T>& gra_vector;
size_t gu32_index;
};
iterator<Node> begin()
{
return iterator<Node>(gast_my_array, 0);
}
iterator<Node> end()
{
return iterator<Node>(gast_my_array, gast_my_array.size());
}
private:
std::vector<Node> gast_my_array;
};
int main(void)
{
My_class my_class_instance;
for (My_class::iterator<My_class::Node> cl_custom_iterator=my_class_instance.begin();cl_custom_iterator!=my_class_instance.end();cl_custom_iterator++)
{
int n_payload = cl_custom_iterator.get_payload();
My_class::Node st_node = cl_custom_iterator.get_node();
//std::cout << "get_payload: " << cl_custom_iterator.get_payload();
std::cout << "get_payload: " << n_payload << "\n";
printf("%p | get_payload: %d | get_node.n_payload: %d\n", cl_custom_iterator, n_payload, st_node.n_payload);
}
return 0;
}
这是我在我的机器上用mingw -std=c++11编译得到的输出
get_payload被馈送到std::cout并从节点手动提取结构成员给予正确的结果33、34......
get_payload输入到printf,打印出错误的数字1,2,...
Push 1 | Payload: 34
Push 2 | Payload: 35
Push 3 | Payload: 36
Push 4 | Payload: 37
get_payload: 33
006efec8 | get_payload: 0 | get_node.n_payload: 33
get_payload: 34
006efec8 | get_payload: 1 | get_node.n_payload: 34
get_payload: 35
006efec8 | get_payload: 2 | get_node.n_payload: 35
get_payload: 36
006efec8 | get_payload: 3 | get_node.n_payload: 36
get_payload: 37
006efec8 | get_payload: 4 | get_node.n_payload: 37
Process returned 0 (0x0) execution time : 0.141 s
Press any key to continue.
我不知道我做错了什么。
固定代码
#include <iostream>
#include <vector>
class My_class
{
public:
struct Node
{
int n_payload;
};
//Constructor with example
My_class()
{
Node st_node;
for (int cnt = 0; cnt < 5; cnt++)
{
st_node.n_payload = 33+cnt;
gast_my_array.push_back( st_node );
std::cout << "Push " << cnt << " | Payload: " << gast_my_array[cnt].n_payload << "\n";
}
}
//iterator
template <typename T>
class iterator
{
public:
//! @brief constructor for the custom iterator
iterator(std::vector<T>& ira_parent_vector, size_t in_starting_index = 0) :
gra_vector(ira_parent_vector),
gu32_index(in_starting_index)
{
//Do nothing
return;
}
iterator<T>& operator++()
{
gu32_index++;
return *this;
}
iterator<T> operator++(int)
{
iterator<T> tmp(*this);
gu32_index++;
return tmp;
}
//FIX: I overload the * operator to get a reference to the element of std::vector of which I can easily get the address and content
T &operator *()
{
return gra_vector[gu32_index];
}
bool operator==(const iterator<T>& icl_rhs_iterator) const
{
return gu32_index == icl_rhs_iterator.gu32_index;
}
bool operator!=(const iterator<T>& icl_rhs_iterator) const
{
return gu32_index != icl_rhs_iterator.gu32_index;
}
private:
std::vector<T>& gra_vector;
size_t gu32_index;
};
iterator<Node> begin()
{
return iterator<Node>(gast_my_array, 0);
}
iterator<Node> end()
{
return iterator<Node>(gast_my_array, gast_my_array.size());
}
private:
std::vector<Node> gast_my_array;
};
int main(void)
{
My_class my_class_instance;
for (My_class::iterator<My_class::Node> cl_custom_iterator=my_class_instance.begin();cl_custom_iterator!=my_class_instance.end();cl_custom_iterator++)
{
//FIX: printf has undefined behaviour with %p of an object. std::cout of the address of a reference will print out the address
std::cout << "iterator address: " << &*cl_custom_iterator << " | payload: " << (*cl_custom_iterator).n_payload << "\n";
}
return 0;
}
输出(正确):
Push 0 | Payload: 33
Push 1 | Payload: 34
Push 2 | Payload: 35
Push 3 | Payload: 36
Push 4 | Payload: 37
iterator address: 0x711720 | payload: 33
iterator address: 0x711724 | payload: 34
iterator address: 0x711728 | payload: 35
iterator address: 0x71172c | payload: 36
iterator address: 0x711730 | payload: 37
Process returned 0 (0x0) execution time : 0.109 s
Press any key to continue.
1条答案
按热度按时间jogvjijk1#
像
printf
这样的C函数对迭代器这样的C++类型一无所知,这只会编译,因为printf
是可变函数,因此没有对它的参数进行类型检查。你可以试试这个
使用
&*cl_custom_iterator
应确保参数是指针,这是%p
说明符所要求的。虽然看了
iterator
类,但我不确定它是否会编译。