问题描述
关于编译器如何评估某些内容的快速问题。在下面的代码中,我想知道我写的是否是一个好主意,或者我是否应该更明确。
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() 方法中直接使用迭代器在功能上是否等效?
解决方法
const pos_products = await db.pos_products.get({id: idProduct});
console.log(pos_products.value);
//OR
const { value: pos_products } = await db.pos_products.get({id: idProduct});
console.log(pos_products);
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
。如果您返回对同一个 std::array<uint8_t,6>
的引用,那么该行将是可行的。
另一方面,这段代码:
std::array<uint8_t,6>
使用起来是安全的,因为 std::array<uint8_t,6> temp = Checksum(data);
data.insert(data.end(),temp.begin(),temp.end());
是同一个 temp
对象。