左闭右开区间更不易出边界错误,因为right始终表示“搜索范围不包含的首个位置”,循环条件统一用left
为什么左闭右开区间比左闭右闭更不容易出边界错误
因为
right始终表示“搜索范围不包含的首个位置”,循环条件统一用left ,无需纠结 <code>mid加减 1 后是否越界。所有边界操作(比如right = mid)都天然安全,不用像左闭右闭那样在right = mid - 1时担心下溢。模板函数怎么写才能支持任意随机访问迭代器和自定义比较
必须用
std::iterator_traits提取迭代器类型,并让比较函数可选,默认用。关键点是:迭代器要满足 <code>RandomAccessIterator要求,否则mid = first + (last - first) / 2编译不过。template<typename it typename t compare="std::less<typename" std::iterator_traits>::value_type>> It lower_bound(It first, It last, const T& val, Compare comp = Compare{}) { while (first <h3>调用时传数组、vector 或 raw 指针要注意什么</h3> <p>左闭右开区间的 <code>last</code> 必须是“末尾后一个位置”——这是最容易错的地方。常见错误包括:</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a> <p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <ul> <li>对 <code>std::vector<int> v</int></code>,传 <code>v.begin(), v.end()</code> 正确;传 <code>v.data(), v.data() + v.size()</code> 也正确;但传 <code>v.data(), v.data() + v.size() - 1</code> 就错了</li> <li>对 C 风格数组 <code>int arr[5]</code>,必须传 <code>arr, arr + 5</code>,不能传 <code>arr, &arr[4]</code> </li> <li>如果容器为空,<code>first == last</code>,循环不进入,直接返回 <code>first</code>,逻辑依然成立</li> </ul> <h3>和 <code>std::lower_bound</code> 的行为差异在哪</h3> <p>你写的模板如果完全按上述实现,行为就和 <code>std::lower_bound</code> 一致——返回第一个不小于 <code>val</code> 的位置。但注意两点:</p> <ul> <li> <code>std::lower_bound</code> 要求范围已排序,你的模板也一样;没排序结果未定义</li> <li>如果你用自定义 <code>Compare</code>,比如 <code>std::greater<int></int></code>,那搜索的是“第一个不大于 <code>val</code> 的位置”,此时数据必须是降序排列,否则结果不可靠</li> <li>性能上无差异,都是 O(log n),但模板实例化可能略微增加编译时间</li> </ul> <p>真正容易被忽略的是:当目标不存在时,返回的迭代器可能等于 <code>last</code>,也就是越界位置——这时候解引用会崩溃,用之前务必检查是否 <code>!= last</code>。</p></typename>
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











