我很难从字符串中创建向量。有人能解释一下下面这4种情况的区别吗?根据cplusplus.com的说法,我希望Case 1能像Case 2一样工作,原因也一样奇怪,但事实并非如此。
typedef std::vector<uint8_t> uint8vec_t;
std::string keySecret ()
{
return std::string ("SomeSecret");
}案例1
// throws std::bad_alloc
uint8vec_t vSecret (keySecret ().begin (), keySecret ().end ());案例2
// results in a vector with strange length
uint8vec_t vSecret (keySecret ().begin (), keySecret ().begin () + keySecret ().length ());案例3
// throws std::bad_alloc
uint8vec_t vSecret (&keySecret ()[0], &keySecret ()[keySecret ().length ()]);案例4
// throws std::bad_alloc
uint8vec_t vSecret (&keySecret ()[0], &keySecret ()[0] + keySecret ().length ());发布于 2014-11-25 14:32:30
它们都很糟糕,在第二种情况下,你碰巧得到了看起来是正确的行为。问题是keySecret每次都返回一个不同的std::string对象。您不能在一个调用begin,在另一个调用end,并期望它们在任何方面都是相关的。
相反,您应该调用keySecret一次,创建一个本地副本,然后在该单个本地对象上调用begin和end。
发布于 2014-11-25 14:41:24
调用keySecret()之后,内存中有两个不同的字符串:
...x..x....SomeSecret\0..x.x.x...x..x..x.x...SomeSecret\0....x.x..x.x..
^ ^ ^ ^
begin1 end1 begin2 end2然后,您将尝试使用以下两种方法创建一个向量
vector<char> v(begin1, end2);或
vector<char> v(begin2, end1);(取决于哪个字符串碰巧在内存中较早,哪个字符串由哪个keySecret()调用返回)。
第一个将分配end2 - begin1字节并将"SomeSecret\0..x.x.x...x..x..x.x...SomeSecret\0"复制到该内存中,在两个迭代器之间使用任意数量的字节,其中包含字符串之间的内存中的任何内容。这是未定义的行为,原因是读取了分配给第一个字符串的内存结束后。
第二种方法将尝试查找距离为负值的end1 - begin2,因此将其包装为一个非常大的无符号数字,并试图分配很多字节失败,引发一个bad_alloc异常。
在这两种情况下,对指向不同对象的两个无关指针执行指针算术是未定义的行为,因此理论上任何事情都可能发生。在实践中,结果可以被合理地解释,如上面所示(尽管对于第一种情况来说,分段错误并不是一个令人惊讶的结果,而不是一个包含错误内容的向量)。
https://stackoverflow.com/questions/27129317
复制相似问题