Clang抱怨:"指针由一个临时数组初始化"

时间:2015-07-03 17:52:16

标签: c++ clang allocation

我有一组(指向)不同长度的数组,我学会了我可以使用复合文字来定义:

const uint8_t *const minutes[] = {
    (const uint8_t[]) {END},
    (const uint8_t[]) {1, 2, 3, 4, 5 END},
    (const uint8_t[]) {8, 9, END},
    (const uint8_t[]) {10, 11, 12, END},
    ...
}; 

gcc接受这个很好,但是clang说:pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression。这是什么意思?代码似乎正在工作,但是当它们指向不再分配的内存时,很多事情似乎似乎。这是我需要担心的吗? (最终我只需要它与gcc一起工作。)

更新:有些事可疑。它说here

  

复合文字产生左值。这意味着您可以获取复合文字的地址,该复合文字是复合文字声明的未命名对象的地址。只要复合文字没有const限定类型,就可以使用指针来修改它。

   `struct POINT *p;
   p = &(struct POINT) {1, 1};

这个示例代码似乎正在完成我正在尝试做的事情:指向由复合文字定义的内容的指针。 clang错误消息合法吗?当用clang或gcc编译时,这最终会指向未分配的内存吗?

更新2 : 找到一些documentation:"在C中,复合文字指定具有静态或自动存储持续时间的未命名对象。 在C ++中,复合文字指定一个临时对象,它只能存在于其完整表达式的结尾。"所以似乎clang是正确的警告这一点,gcc可能也应该如此,但即使-Wall -Wextra也没有。

我无法猜测为什么从C ++中删除了有用的C功能,并且没有提供完成相同功能的优雅替代方法。

3 个答案:

答案 0 :(得分:3)

嗯,铿锵是对的,这应该这样做:

namespace elements
{
    const uint8_t row1[] = {END};
    const uint8_t row2[] = {1, 2, 3, 4, 5, END};
    ...
}
const uint8_t *const minutes[] = {
    elements::row1,
    elements::row2,
    ...
}; 

您可以考虑使用更多C ++解决方案,例如使用std::tuple

#include <tuple>

constexpr auto minutes = std::make_tuple(
    std::make_tuple(), 
    std::make_tuple(1,2,3,4,5),
    std::make_tuple(8,9,10)); 

#include <iostream>
#include <type_traits>
int main() {
    std::cout << std::tuple_size<decltype(minutes)>::value << std::endl;
    std::cout << std::tuple_size<std::remove_reference_t<decltype(std::get<1>(minutes))>>::value << std::endl;
}

答案 1 :(得分:2)

更新:感谢deniss指出原始解决方案中的缺陷。

static constexpr uint8_t END = 0xff;

template<uint8_t...x>
const uint8_t* make()
{
    static const uint8_t _[] = { x..., END };
    return _;
}

const uint8_t* const array[] = {
    make<>(),
    make<1, 2, 3, 4, 5>(),
    make<8, 9>(),
    make<10, 11, 12>()
};

答案 2 :(得分:1)

嗯,这意味着,这个表达

(const uint8_t[]) {1, 2, 3, 4, 5 END},

创建一个临时对象 - 临时对象,因为它没有任何名称可以超出它所属的表达式 - 它在完整表达式的末尾被销毁,这意味着:

 };

定义“完整表达式”,此时所有临时对象都将被销毁,指针数组minutes保存指向销毁的指针对象,这就是编译器发出警告的原因。

希望有所帮助。