将指向std :: pair的指针作为指向数组的指针传递是否安全?

时间:2018-02-12 09:19:52

标签: c++ pointers

我可以安全地假设std::pair的第一个元素的地址可以用作两个元素数组的地址吗?当然,这对中的两个元素都是相同的类型。以下代码适用于g ++ 7.2,clang 3.8和vc ++ 14

void foo(int* a)
{
    std::cout << std::to_string(a[0]) << ", " << std::to_string(a[1]) << std::endl;
}

int main()
{
    std::pair<int, int> bar(42, 24);
    foo(&bar.first);
    return 0;
}

由于std::pair是一个相当简单的类,我确信这个案例可以概括,但我不确定到什么程度。例如,它是模板类对问题有什么影响吗?

如果我不能安全地做到这一点,为什么?如果它被认为是有效的代码,那么这有什么保证呢?

2 个答案:

答案 0 :(得分:4)

将我的评论写成答案:

除了数组(如MSalters所指出的),绝对不允许读取超出对象边界的内容。虽然单个变量可以被认为是长度为1的数组(因此a[0]因其定义为*(a+0)而被允许),所以读取其不存在的第二个元素&#34; via a[1]是未定义的行为,因为它超出了bar.first的边界。这两个对象可能是较大聚合对象(其实现未知)的一部分,但不会改变它。

请注意,像这样的许多边界违规都可以使用已知的体系结构,编译器,库和编译器选项;这个特定的应该在任何地方都可以使用,因为int被设计为在给定的机器上具有自然的单词大小,因此可以在结构中没有填充的情况下对齐,std::pair当然是;但是没有保证,包括恶意编译器。实际上,呈现的程序(即作为一个翻译单元)可以静态地证明是不正确的。编译器可以检测到并拒绝编译。

答案 1 :(得分:2)

cpp引用没有说明如何定义模板化的struct std :: pair(http://en.cppreference.com/w/cpp/utility/pair)。 不能保证第一个和第二个参数将被打包在一起。即使大多数实现可能看起来像

template<class A, class B>
struct pair {
    [...]
    A first;
    B second;
    [...]
}

对于int,您的代码可能有效。对于其他类型,假设std :: pair的内部结构看起来是非常不安全的。

如果需要元素的整数数组,则必须将它们复制到一个单独的位置。