方法调用中的迭代器/功能等价/最佳实践
Iterators in Method call / Functional Equivalence / Best Practise
关于编译器如何计算某些东西的快速问题。在下面的代码中,我想知道我写的是不是一个好主意,或者我是否应该更明确。
constexpr auto Checksum = [](const std::vector<uint8_t>& values) -> std::array<uint8_t, 6> {
std::vector<uint8_t> data{ 0x03, 0x03, 0x00, 0x17, 0x13 };
data.insert(data.end(), values.begin(), values.end());
data.resize(data.size() + 6);
uint32_t c = 1;
for (const auto v_i : data)
{
uint8_t c0 = c >> 25;
c = ((c & 0x1ffffff) << 5) ^ v_i;
if (c0 & 1)
c ^= 0x3b6a57b2;
if (c0 & 2)
c ^= 0x26508e6d;
if (c0 & 4)
c ^= 0x1ea119fa;
if (c0 & 8)
c ^= 0x3d4233dd;
if (c0 & 16)
c ^= 0x2a1462b3;
}
c ^= 0x2bc830a3;
std::array<uint8_t, 6> ret;
for (size_t i = 0; i < 6; i++)
ret[i] = (c >> (5 * (5 - i))) & 31;
return ret;
};
std::vector<uint8_t> data = ConvertBits();
data.insert(data.end(), Checksum(data).begin(), Checksum(data).end()); // <------------ What is happening here?
显然 .insert() 的参数保证在使用前完全构建,但是迭代器是在一个不可见的临时对象上工作吗?我应该更明确地做:
std::array<uint8_t, 6> temp = Checksum(data);
data.insert(data.end(), temp.begin(), temp.end());
上述代码和直接在 .insert() 方法中使用迭代器在功能上是否等同?
constexpr auto Checksum = [](const std::vector<uint8_t>& values) -> std::array<uint8_t, 6>
{
//...
std::array<uint8_t, 6> ret;
//...
return ret;
}
//...
data.insert(data.end(), Checksum(data).begin(), Checksum(data).end());
data.insert
调用未定义的行为,因为 Checksum(data).begin()
和 Checksum(data).end()
是两个完全不同的 std::array
容器的迭代器。
Checksum
的 return 语义是按值的,您正在 returning std::array<uint8_t, 6>
。如果您 return 引用相同的 std::array<uint8_t, 6>
,那么该行将是可行的。
另一方面,这段代码:
std::array<uint8_t, 6> temp = Checksum(data);
data.insert(data.end(), temp.begin(), temp.end());
可以安全使用,因为 temp
是同一个 std::array
对象。
关于编译器如何计算某些东西的快速问题。在下面的代码中,我想知道我写的是不是一个好主意,或者我是否应该更明确。
constexpr auto Checksum = [](const std::vector<uint8_t>& values) -> std::array<uint8_t, 6> {
std::vector<uint8_t> data{ 0x03, 0x03, 0x00, 0x17, 0x13 };
data.insert(data.end(), values.begin(), values.end());
data.resize(data.size() + 6);
uint32_t c = 1;
for (const auto v_i : data)
{
uint8_t c0 = c >> 25;
c = ((c & 0x1ffffff) << 5) ^ v_i;
if (c0 & 1)
c ^= 0x3b6a57b2;
if (c0 & 2)
c ^= 0x26508e6d;
if (c0 & 4)
c ^= 0x1ea119fa;
if (c0 & 8)
c ^= 0x3d4233dd;
if (c0 & 16)
c ^= 0x2a1462b3;
}
c ^= 0x2bc830a3;
std::array<uint8_t, 6> ret;
for (size_t i = 0; i < 6; i++)
ret[i] = (c >> (5 * (5 - i))) & 31;
return ret;
};
std::vector<uint8_t> data = ConvertBits();
data.insert(data.end(), Checksum(data).begin(), Checksum(data).end()); // <------------ What is happening here?
显然 .insert() 的参数保证在使用前完全构建,但是迭代器是在一个不可见的临时对象上工作吗?我应该更明确地做:
std::array<uint8_t, 6> temp = Checksum(data);
data.insert(data.end(), temp.begin(), temp.end());
上述代码和直接在 .insert() 方法中使用迭代器在功能上是否等同?
constexpr auto Checksum = [](const std::vector<uint8_t>& values) -> std::array<uint8_t, 6>
{
//...
std::array<uint8_t, 6> ret;
//...
return ret;
}
//...
data.insert(data.end(), Checksum(data).begin(), Checksum(data).end());
data.insert
调用未定义的行为,因为 Checksum(data).begin()
和 Checksum(data).end()
是两个完全不同的 std::array
容器的迭代器。
Checksum
的 return 语义是按值的,您正在 returning std::array<uint8_t, 6>
。如果您 return 引用相同的 std::array<uint8_t, 6>
,那么该行将是可行的。
另一方面,这段代码:
std::array<uint8_t, 6> temp = Checksum(data);
data.insert(data.end(), temp.begin(), temp.end());
可以安全使用,因为 temp
是同一个 std::array
对象。