2013-02-26 71 views
1

考虑下面的代码:是否可以存储一组指针导致未定义的行为?

#include <iostream> 

int main(int argc, char ** argv) { 

    std::set<int*> ints; 

    for (int i = 0; i < 10; i ++) { 
    int * k = new int(i); 
    ints.insert(k); 
    } 

    for (auto i : ints) { 
    // some order-sensitive operations, for example: 
    std::cout << (*i) << " "; 
    } 

    return 0; 
} 

当第二环是其中的元件从该组所采取的顺序是敏感的。在程序的不同运行中,执行这种程序的结果可能会有所不同吗?

据我所知,std::set内部排序元素。由于内存中的分配不一定会增加地址,所以可能(但不太可能),该程序的输出不会是0 1 2 3 4 5 6 7 8 9

+0

我会说,即使顺序可能是不确定的,它仍然不是通常意义上的未定义行为(HTTP ://en.wikipedia。组织/维基/ Undefined_behavior)。 – Reunanen 2013-02-26 10:45:48

+0

@Pukku是的,我用了错误的名词。它更接近“未指定”的行为。 – Saage 2013-02-26 10:56:45

回答

5

是的,他们可能会不同,但它不会因为UB。

有被执行这里定义的两件事情:

  • 方式std::less<int*>做了排序(虽然大多数实现,你会看到一个“自然”排序)
  • operator new返回的地址可能会或可能不会每次都是一样的。这在分配器上很可能会因您的实现使用而有所不同,并且两种方式(确定性的和看似随机的)都在野外被看到。 (请注意,当您通过例如valgrind运行程序时,顺序可能始终相同,但与本机运行时不同)。

所以不要依赖这个存在于你有兴趣在任何特定的顺序。

0

使用手册,卢克。

std::set documentation in MSDN

的STL集是:

(...)

排序,因为它的元件由关键值的容器内,根据与指定的比较函数排序。

指针是简单的整数,所以这些变量将按其地址排序。内存管理器可以在非常不同的地方分配这些变量,所以你不能保证它们的顺序(就其值而言)将被保留。

然而,现在看来,你可以提供自己的比较函数:

std::set::set() documentation on MSDN

然后您可以组的方式,其中最适合你的元素进行排序。

+0

对于所描述的Microsoft实现,指针几乎是int,除了Win64以外,其实它们都不是。在其他体系结构中,指针可能更像整型。最着名的例外是古典x86,它们是怪异的20位野兽。 – MSalters 2013-02-26 19:15:09

2

这不是标准意义上的“未定义的行为”(可以发生任何事情)。

但是,在分配内存时,您肯定会得到指向您的指针。该标准没有说明免费商店的组织方式,也没有说明不同分配地址的顺序。

相关问题