protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (container is ListViewItem cont)
{
if (cont.Tag != null && long.TryParse(cont.Tag.ToString(), out var token))
{
cont.UnregisterPropertyChangedCallback(ListViewItem.IsSelectedProperty, token);
}
cont.Tag = cont.RegisterPropertyChangedCallback(ListViewItem.IsSelectedProperty, (s, e) =>
{
cont.ContentTemplateSelector = null;
cont.ContentTemplateSelector = this;
});
if (cont.IsSelected)
{
return SelectedItemTemplate;
}
return DefaultTemplate;
}
return DefaultTemplate;
}
根据我的理解,pop_back()假设弹出向量的最后一个索引,我对编译的期望是给我一个错误;但是,控制台上的输出表示为:
3 3
有人会解释为什么这个程序的编译成功吗?
谢谢。
答案 0 :(得分:4)
vector<>::operator[]()
不会检查向量的大小,因此您的代码会产生未定义的行为。
在您的特定情况下,向量在大小(向量中的项目数)缩小,而不是容量(基础数组的大小)当你致电pop_back()
时。这意味着第二个VectorName[1]
指向未使用但存在的内存。例如,如果我们稍微编辑您的示例以检查容量和大小:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> VectorName;
VectorName.push_back(2); // |[2]|
VectorName.push_back(3); // |[2, 3]|
VectorName.pop_back(); // |[2], 3|
cout << VectorName.size() << endl;
cout << VectorName.capacity() << endl;
}
输出结果为:
1
2
您可以在此处查看一个有效的示例:http://coliru.stacked-crooked.com/a/70d5141bdc375b48
正如您所看到的,向量的大小是正确的(1项),但是对VectorName.pop_back()
的调用不会降低容量,因此3
仍然存在于向量中,但它是不可访问。
通过在调用VectorName.pop_back()
后访问第二个项目,您将导致未定义的行为。在您的情况下,您获得3
,但使用不同的编译器,体系结构或计算机编译应用程序可能会导致应用程序崩溃(或更糟)!
使用vector<int>::at()
代替vector<int>::operator[]()
会抛出std::out_of_range
异常,导致程序崩溃。这是因为at()
函数会检查向量的大小,如果您尝试访问向量中的越界位置,则会抛出异常。也就是说,不要依赖at()
函数来检查矢量访问,更喜欢在调用size()
之前检查矢量的VectorName[1]
。
例如,通过再次对代码进行次要编辑,我们可以看到使用at()
函数时会发生什么:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> VectorName;
VectorName.push_back(2);
VectorName.push_back(3);
cout << VectorName.at(1) << endl;
VectorName.pop_back();
cout << VectorName.at(1) << endl;
return 0;
}
3
在抛出'std :: out_of_range'
的实例后终止调用what():vector :: _ M_range_check:__n(即1)&gt; = this-&gt; size()(即1)
bash:第7行:4793中止(核心转储)./a.out
直播示例:http://coliru.stacked-crooked.com/a/8226be85196f54fe
“编译错误”还有一件事。在访问向量之前,编译器不会尝试检查向量的大小,因此编译器将很乐意编译代码而不会出现错误或警告。作为开发人员,您可以对代码执行边界检查。