unique_ptr 上的增量会导致用户定义运算符出现意外行为!=
Increment on unique_ptr causes unexpected behaviour of user-defined operator!=
这是一个非常具体的问题,解释起来有点长,所以请耐心等待我尽我所能总结一下。
我创建了两种用户类型,第一种在第二种内部使用:
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
在 main()
中,我创建了一个 unique_ptr
到 myType
的 vector
并这样填充它:
vector<unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
因此每个元素的 start
和 stop
的 val
如下:
start:0 stop:1
start:1 stop:2
start:2 stop:3
start:3 stop:4
start:4 stop:5
start:5 stop:6
start:6 stop:7
start:7 stop:8
start:8 stop:9
start:9 stop:10
start
应始终与之前的 stop
相同(本例中就是这种情况)。为了检查这一点,我尝试了以下操作:
for (auto it = v.begin(); it != --v.end(); )
{
if ((*it)->stop != (*(++it))->start)
cout << "1";
}
令我惊讶的是,输出是:111111111
,当它们应该完全相同时却完全不同。
我尝试了一些其他的东西来尝试理解错误的根源。我用
替换了循环内部
mySubType stop = (*it)->stop;
mySubType next_start = (*(++it))->start;
if (stop != next_start)
cout << "2";
然后
if ((*it)->stop.val != (*(++it))->start.val)
cout << "3";
这些都没有打印任何东西(所有测试都被正确解决为相等)。
这仅在使用 unique_ptr
时发生(vector<myType>
没有同样的问题)。我也尝试使用 post-increment 但我得到了完全相同的结果。
有人知道为什么会这样吗?
我知道有很多方法可以解决这个问题(例如上面的 2 个)。我感兴趣的是为什么会发生这种行为。
if语句中的表达式
if ((*it)->stop != (*(++it))->start)
有未定义的行为。
看来你的意思是下面的循环
#include <iterator>
// ...
for (auto it = v.begin(); it != v.end(); ++it )
{
auto next = std::next( it );
if ( next != v.end() && (*it)->stop != (*( next ))->start)
std::cout << "1";
}
您可以使用标准算法 std::adjacent_find
而不是 for 循环。例如
#include <iostream>
#include <memory>
#include <vector>
#include <iterator>
#include <algorithm>
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
int main()
{
std::vector<std::unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( std::unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
auto it = std::adjacent_find( std::begin( v ), std::end( v ),
[]( const auto &left, const auto &right )
{
return left->stop != right->start;
} );
if ( it != std::end( v ) ) std::cout << "there is an error\n";
else std::cout << "The sequence is correct\n";
}
程序输出为
The sequence is correct
这是一个非常具体的问题,解释起来有点长,所以请耐心等待我尽我所能总结一下。
我创建了两种用户类型,第一种在第二种内部使用:
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
在 main()
中,我创建了一个 unique_ptr
到 myType
的 vector
并这样填充它:
vector<unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
因此每个元素的 start
和 stop
的 val
如下:
start:0 stop:1
start:1 stop:2
start:2 stop:3
start:3 stop:4
start:4 stop:5
start:5 stop:6
start:6 stop:7
start:7 stop:8
start:8 stop:9
start:9 stop:10
start
应始终与之前的 stop
相同(本例中就是这种情况)。为了检查这一点,我尝试了以下操作:
for (auto it = v.begin(); it != --v.end(); )
{
if ((*it)->stop != (*(++it))->start)
cout << "1";
}
令我惊讶的是,输出是:111111111
,当它们应该完全相同时却完全不同。
我尝试了一些其他的东西来尝试理解错误的根源。我用
替换了循环内部mySubType stop = (*it)->stop;
mySubType next_start = (*(++it))->start;
if (stop != next_start)
cout << "2";
然后
if ((*it)->stop.val != (*(++it))->start.val)
cout << "3";
这些都没有打印任何东西(所有测试都被正确解决为相等)。
这仅在使用 unique_ptr
时发生(vector<myType>
没有同样的问题)。我也尝试使用 post-increment 但我得到了完全相同的结果。
有人知道为什么会这样吗?
我知道有很多方法可以解决这个问题(例如上面的 2 个)。我感兴趣的是为什么会发生这种行为。
if语句中的表达式
if ((*it)->stop != (*(++it))->start)
有未定义的行为。
看来你的意思是下面的循环
#include <iterator>
// ...
for (auto it = v.begin(); it != v.end(); ++it )
{
auto next = std::next( it );
if ( next != v.end() && (*it)->stop != (*( next ))->start)
std::cout << "1";
}
您可以使用标准算法 std::adjacent_find
而不是 for 循环。例如
#include <iostream>
#include <memory>
#include <vector>
#include <iterator>
#include <algorithm>
struct mySubType {
int val;
mySubType () {}
mySubType ( int _val) : val(_val){}
bool operator!=(const mySubType& rhs) const { return val != rhs.val; }
};
struct myType {
mySubType start;
mySubType stop;
myType () {}
myType (mySubType _start, mySubType _stop) : start(_start), stop(_stop) {}
};
int main()
{
std::vector<std::unique_ptr<myType>> v;
for (int i = 0; i < 10; ++i)
v.push_back( std::unique_ptr<myType>(new myType( mySubType(i), mySubType(i+1))) );
auto it = std::adjacent_find( std::begin( v ), std::end( v ),
[]( const auto &left, const auto &right )
{
return left->stop != right->start;
} );
if ( it != std::end( v ) ) std::cout << "there is an error\n";
else std::cout << "The sequence is correct\n";
}
程序输出为
The sequence is correct