Make objects in range declarations immutable by default.
Rationale:
- Immutable objects are easier to reason about.
- Prevents accidental or hard-to-notice change of value.
Make objects in range declarations immutable by default.
Rationale:
@Empact I think it better to do (a subset of) the #12158 changes in follow-up PRs to keep this PR as mechanical and easy-to-review as possible. Basically what @laanwj suggested in #12158 (comment) :-)
This PR should hopefully be trivial to review :-)
Yeah, I like it as-is, just suggesting since the &
additions wouldn’t add much if anything to the line count, so it could be viewed as a form of compression.
Anyway, you have my Tested ACK 3299ed7.
make
, make check
and test/test_bitcoin
ran green locally.
244@@ -245,7 +245,7 @@ int BlockAssembler::UpdatePackagesForAdded(const CTxMemPool::setEntries& already
245 CTxMemPool::setEntries descendants;
246 mempool.CalculateDescendants(it, descendants);
247 // Insert all descendants (not yet in block) into the modified set
248- for (CTxMemPool::txiter desc : descendants) {
249+ for (const CTxMemPool::txiter desc : descendants) {
const CTxMemPool::txiter&
?
1602@@ -1603,7 +1603,7 @@ void CConnman::ThreadDNSAddressSeed()
1603
1604 LOCK(cs_vNodes);
1605 int nRelevant = 0;
1606- for (auto pnode : vNodes) {
1607+ for (const auto pnode : vNodes) {
849@@ -850,7 +850,7 @@ void PeerLogicValidation::BlockConnected(const std::shared_ptr<const CBlock>& pb
850 // Erase orphan transactions included or precluded by this block
851 if (vOrphanErase.size()) {
852 int nErased = 0;
853- for (uint256 &orphanHash : vOrphanErase) {
854+ for (const uint256 &orphanHash : vOrphanErase) {
const uint256&
?
2271@@ -2272,7 +2272,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
2272 }
2273 }
2274
2275- for (uint256 hash : vEraseQueue)
2276+ for (const uint256 hash : vEraseQueue)
const &
. Can you review the whole change if you agree with such change?
37@@ -38,7 +38,7 @@ RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
38 CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
39 pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
40
41- for (CTxMemPool::txiter it : setAncestors) {
42+ for (const CTxMemPool::txiter it : setAncestors) {
src/miner.cpp
.
441@@ -442,7 +442,7 @@ void BitcoinApplication::requestShutdown()
442
443 #ifdef ENABLE_WALLET
444 window->removeAllWallets();
445- for (WalletModel *walletModel : m_wallet_models) {
446+ for (const WalletModel *walletModel : m_wallet_models) {
WalletModel*
. Fine to ignore.
531@@ -532,14 +532,14 @@ static UniValue getmempoolancestors(const JSONRPCRequest& request)
532
533 if (!fVerbose) {
534 UniValue o(UniValue::VARR);
535- for (CTxMemPool::txiter ancestorIt : setAncestors) {
536+ for (const CTxMemPool::txiter ancestorIt : setAncestors) {
87@@ -88,7 +88,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
88 int64_t modifySize = 0;
89 CAmount modifyFee = 0;
90 int64_t modifyCount = 0;
91- for (txiter cit : setAllDescendants) {
92+ for (const txiter cit : setAllDescendants) {
3209@@ -3210,7 +3210,7 @@ DBErrors CWallet::ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256
3210 {
3211 AssertLockHeld(cs_wallet); // mapWallet
3212 DBErrors nZapSelectTxRet = WalletBatch(*database,"cr+").ZapSelectTx(vHashIn, vHashOut);
3213- for (uint256 hash : vHashOut)
3214+ for (const uint256 hash : vHashOut)
609@@ -610,7 +610,7 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
610 if ((wss.nKeys + wss.nCKeys + wss.nWatchKeys) != wss.nKeyMeta)
611 pwallet->UpdateTimeFirstKey(1);
612
613- for (uint256 hash : wss.vWalletUpgrade)
614+ for (const uint256 hash : wss.vWalletUpgrade)
utACK 9a4655fd15e632d95651e4681936f8ea13457ae1
These changes should be obviously safe. Adding const
to variable declarations should never introduce problems (as long as the result compiles). The same is true for converting const
variables to references.
97@@ -98,7 +98,7 @@ class NodeImpl : public Node
98 g_connman->GetNodeStats(stats_temp);
99
100 stats.reserve(stats_temp.size());
101- for (auto& node_stats_temp : stats_temp) {
102+ for (const CNodeStats& node_stats_temp : stats_temp) {
stats_temp
is a std::vector<CNodeStats>
, and you can loop over with CNodeStats&
, shouldn’t you also be able to take a const CNodeStats&
without performance implication?
See below:
0std::move(node_stats_temp)
This is a non-const reference so that the elements can be moved rather than copied.
@sipa I disagree. std::move is still allowed on const references, they just… don’t move. One such instance of this is here: #13249 (review)
It’s unlikely to cause issues, only performance reductions, but code that relies on refcounts/lifetimes would potentially be affected. So I’m a bit more nervous about such a sweeping change.
37@@ -38,7 +38,7 @@ RBFTransactionState IsRBFOptIn(const CTransaction &tx, CTxMemPool &pool)
38 CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
39 pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
40
41- for (CTxMemPool::txiter it : setAncestors) {
42+ for (const CTxMemPool::txiter& it : setAncestors) {
@MarcoFalke @promag The remaining txiter
const
ref changes along the line of …
0- for (const CTxMemPool::txiter it : …) {
1+ for (const CTxMemPool::txiter& it : …) {
… are required to make -Wrange-loop-analysis
pass.
Drop const
or keep &
?
const
, since CTxMemPool::txiter
is already a const iterator and the const
does nothing useful, as far as I can see.
@MarcoFalke I expect it to not matter at all, as in most cases the compiler will optimize things far enough to result in nearly identical code for reference or not.
I believe the clang warning code suggests references in case a copy can be avoided. I think we should follow those suggestions, as it has the best performance guarantees ignoring optimizations.
In practice, most iterators are just a single pointer, but some are not (std::vector’s iterators, for example).
const
iterator instead of a const_iterator
is just misleading and could lead to dangerous bugs.
2389@@ -2390,7 +2390,7 @@ std::map<CTxDestination, std::vector<COutput>> CWallet::ListCoins() const
2390 LOCK2(cs_main, cs_wallet);
2391 AvailableCoins(availableCoins);
2392
2393- for (auto& coin : availableCoins) {
2394+ for (const auto& coin : availableCoins) {
const COutput& coin
?
4492@@ -4493,7 +4493,7 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
4493
4494 // Build forward-pointing map of the entire block tree.
4495 std::multimap<CBlockIndex*,CBlockIndex*> forward;
4496- for (auto& entry : mapBlockIndex) {
4497+ for (const auto& entry : mapBlockIndex) {
Most common usage when iterating mapBlockIndex
is
0for (const std::pair<const uint256, CBlockIndex*>& item : mapBlockIndex)
And there is also the above:
0for (const BlockMap::value_type& entry : mapBlockIndex)
(I prefer the 1st).
1569@@ -1570,7 +1570,7 @@ int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wall
1570 // Look up the inputs. We should have already checked that this transaction
1571 // IsAllFromMe(ISMINE_SPENDABLE), so every input should already be in our
1572 // wallet, with a valid index into the vout array, and the ability to sign.
1573- for (auto& input : tx.vin) {
1574+ for (const auto& input : tx.vin) {
const CTxIn& input
(most common usage).
auto
usage.