首页 > 解决方案 > 我可以在初始化之前使用 std::array 成员变量中的 data() 指针吗?发出警告

问题描述

我正在使用指向存储在派生类SelfContained的 std::array 成员中的数据的指针初始化一个基类(例如Matrix<3,3> ),在执行时被警告“在此处使用字段'vdata'未初始化”所以。

该警告是有道理的,但我不确定避免它的最佳方法......代码似乎无论如何都可以工作,但我不喜欢看到警告,所以我正在尝试修复它。

我可能完全错了,但是在这里使用时似乎分配了 std:array vdata,因此即使数组未初始化, data() 指针也应该已经有效。由于我之后立即对其进行初始化,所以我很想忽略警告......但我希望有一种更“正确”的方式......

我已经迭代了几次......以前 std::array 是一个 C 风格的数组,并且抓住指向它的指针不会导致问题。

#include <iostream>
#include <array>

template<class ContainedType>
class SelfContained: public ContainedType{
public:
    typedef ContainedType Type;
    
    static constexpr size_t numel()     {   return Type::numel();}
    
    typedef std::array<double, numel()> DataArray;   //  Data Array Type
    DataArray vdata;
    
    SelfContained(DataArray arry_in): ContainedType(vdata.data()), vdata{arry_in} {} // WARNING: Field 'vdata' is uninitialized when used here
    
};


template <size_t m, size_t n>
class Matrix{
public:
    typedef double DoubleArray[n][m];   //  Data Array Type
    
    DoubleArray* pdata = NULL;        //  Pointer to data array: to be assigned on instantiation to let instance be a specified sub-array of something else.
    
    static constexpr size_t height() {return m;}
    static constexpr size_t width()  {return n;}
    static constexpr size_t numel()  {return m*n;}
    
    Matrix(double* p) noexcept : pdata{(DoubleArray*)p}{}

    // Element reference getters (mostly for internal convenience)
    template<typename ...Args>
    double& data(Args... vals){
        return get_data(*this, vals...);
    }
    template<typename ...Args>
    const double& data(Args... vals) const{
        return get_data(*this, vals...);
    }
    
    // Print Matrix
    void print() const {
        for (size_t j=0; j<height(); j++){
            for(size_t k=0;k<width(); k++){
                std::printf("%+15.7f ",data(j,k));
                //std::printf("%+4.1f ",data(j,k));
            } std::printf("\n");
        } std::printf("\n");
    }
    
private:
    
    // Helper functions for public element-reference getters ...
    // weird, but minimizes code dupication (const/non-const) by putting the guts here
    template<typename InstanceType>
    static auto get_data(InstanceType& instance, size_t row) -> decltype(instance.data(row)) {
        assert(row >= 0 && row < instance.numel());
        return (*(instance.pdata))[0][row];
    }
    template<typename InstanceType>
    static auto get_data(InstanceType& instance, size_t row, size_t col) -> decltype(instance.data(row,col)) {
        assert(col >= 0 && col < instance.width());
        assert(row >= 0 && row < instance.height());
        return (*(instance.pdata))[col][row];
    }
};

constexpr std::array<double,9> x0 = {1,0,0,0,2,0,0,0,3};

int main(int argc, const char * argv[]) {

    
    SelfContained<Matrix<3,3>>(x0).print();
    
    return 0;
}

给出警告: 在此处使用字段“vdata”时未初始化

输出:

     +1.0000000      +0.0000000      +0.0000000 
     +0.0000000      +2.0000000      +0.0000000 
     +0.0000000      +0.0000000      +3.0000000 

非常感谢任何帮助。谢谢!

标签: c++

解决方案


据我所知,在初始化vdata.begin()之前调用在vdata技术上是 UB,即使成员函数不需要接触任何成员。

然而,另一个问题是(DoubleArray*)p。通过重新解释的指针进行访问,就好像它指向 a 一样,DoubleArray当它实际上并没有指向这样的对象时,它具有未定义的行为。


推荐阅读