82-CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash() {}
83-CTransaction::CTransaction(const CMutableTransaction &tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
84-CTransaction::CTransaction(CMutableTransaction &&tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
85+CTransaction::CTransaction() : vin(), vout(), nVersion(CTransaction::CURRENT_VERSION), nLockTime(0), hash{}, m_witness_hash{nullptr} {}
86+CTransaction::CTransaction(const CMutableTransaction& tx) : vin(tx.vin), vout(tx.vout), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
87+CTransaction::CTransaction(CMutableTransaction&& tx) : vin(std::move(tx.vin)), vout(std::move(tx.vout)), nVersion(tx.nVersion), nLockTime(tx.nLockTime), hash{ComputeHash()}, m_witness_hash{ComputeWitnessHash()} {}
I believe you could remove some of the boilerplate and repetition here using member initialization in the header:
0const std::unique_ptr<const uint256> m_witness_hash = ComputeWitnessHash();
It would be nice to do this for the other members, too.
I wonder what would be the execution order in this case? ComputeWitnessHash
calls SerializeHash(*this, ...)
so other members must be initialized before.
I wonder what would be the execution order in this case? ComputeWitnessHash calls SerializeHash(*this, …) so other members must be initialized before.
Execution order always the matches order members are declared in the class, not the order initializations are written in the constructor (compilers will warn if the orders differ), so this wouldn’t change behavior. You can see https://isocpp.org/wiki/faq/ctors#ctor-initializer-order for discussion about this.
We couldn’t do the same for the hash
member, I guess, so will leave this as is for now.