You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义basic_point模板类触发Access Violation问题求助

自定义点类型代码运行时触发Access Violation的原因分析

我尝试自定义点类型,先通过Numeric概念约束类型,实现封装数组的basic_point模板类,再通过组合方式实现关联数组元素的Point2D模板类。测试代码编译通过,但运行时触发Access Violation,请问原因是什么?

// concept
template<typename T>
concept Numeric = requires(T param)
{
    requires std::is_integral_v<T> || std::is_floating_point_v<T>;
    requires !std::is_same_v<bool, T>;
    requires std::is_arithmetic_v<decltype(param +1)>;
    requires !std::is_pointer_v<T>;
};

// Point<T,n>
template <Numeric T, size_t dim = 2 > 
struct basic_point {
    constexpr auto inline copy( basic_point<T,dim> const& p) {
        std::copy(p, p + dim * sizeof(p[0]), array.begin()); 
    }
    auto inline copy( T const (&p)[dim]) { 
        std::copy(p, p + dim * sizeof(p[0]), array.begin()); 
    }
    auto inline copy( T const& val) noexcept { 
        for (auto& a : array) 
            a = val; 
    }
    // new constructor
    constexpr basic_point( T const (&pt)[dim])           { copy(pt); }
    // copy constructor
    constexpr basic_point( basic_point<T,dim> const& p)  { copy(p);  }
    // default constructor
    constexpr basic_point( T dt = 0 ) noexcept           { copy(dt); }
    virtual  ~basic_point()         = default ;
 
    constexpr auto inline operator+=( basic_point<T,dim> const& o ) noexcept { 
        for(size_t i = 0; i < dim;i++) 
            array[i] += o.array[i]; 
        }
    constexpr auto inline operator-=( basic_point<T,dim> const& o ) noexcept { for(size_t i = 0; i < dim;i++) array[i] -= o.array[i]; }
    friend constexpr inline auto operator+( basic_point<T,dim> const& a, basic_point<T,dim> const& b ) noexcept { basic_point<T,dim> sum{a};  sum  += b; return sum; }
    friend constexpr inline auto operator-( basic_point<T,dim> const& a, basic_point<T,dim> const& b ) noexcept { basic_point<T,dim> rest{a}; rest -= b; return rest;}
    std::array<T,dim> array;
};

//Point2D<T> 
template<Numeric T = size_t> struct Point2D {
        constexpr Point2D(T const (&p)[2])  {
            data = p;
            x = data.array[0];
            y = data.array[1];
         }
        Point2D(Point2D const& o) : x(o.x),y(o.y){}
       
        void operator+=( Point2D const& other ) {
            x += other.x;
            y += other.y;
        }
    
        void operator-=( Point2D const& other) {
            x -= other.x;
            y -= other.y;
        }
    
        friend Point2D operator+( Point2D const& a, Point2D const& b ) {
            Point2D sum( a );
            sum += b;
            return sum;
        }
    
        friend Point2D operator-( Point2D const&a, Point2D const& b ) {
            Point2D rest( a );
            rest -= b;
            return rest;
        }
        T& x = data.array[0];
        T& y = data.array[1];
        basic_point<T,2> data = basic_point<T,2>(0);  
};

int main(int argc, char* argv[]) {
    const int a[2] = { 1 , 3 };
    const int b[2] = { 1 , 3 }; 
    auto point_a = Point2D(a); 
    auto point_b = Point2D(b);
    auto result = point_a + point_b;
    std::cout << "Result : ("<< result.x << " , " << result.y <<")\n";
    return 0;
}

核心原因分析

  1. 成员初始化顺序错误导致悬垂引用
    C++类成员的初始化顺序严格遵循声明顺序,而非构造函数初始化列表或类内初始化的顺序。在Point2D中,x和y的声明早于data,因此x = data.array[0]和y = data.array[1]会先执行,此时data尚未完成构造,data.array属于未初始化的内存空间,引用绑定到了无效地址,后续访问x、y时必然触发Access Violation。

  2. basic_point的copy函数参数越界
    在basic_point的copy(basic_point<T,dim> const& p)函数中,std::copy(p, p + dim * sizeof(p[0]), array.begin())存在严重错误:p是basic_point对象,并非指针,直接对其做指针算术运算会将对象地址当作数组起始地址,计算出的结束地址会严重超出有效内存范围,导致std::copy访问越界内存,引发运行时错误。

  3. Point2D拷贝构造函数引用初始化错误
    Point2D的拷贝构造函数Point2D(Point2D const& o) : x(o.x),y(o.y){}试图直接初始化引用成员x、y,但引用成员必须绑定到有效对象的内存,此处写法本质是尝试赋值(而非绑定),且因初始化顺序问题,data未构造完成时x、y的绑定仍无效。

修复建议

  • 调整Point2D的成员声明顺序,将data放在x、y之前:
    basic_point<T,2> data = basic_point<T,2>(0);  
    T& x = data.array[0];
    T& y = data.array[1];
    
  • 修正basic_point的copy函数参数,使用数组的迭代器或正确指针:
    constexpr auto inline copy( basic_point<T,dim> const& p) {
        std::copy(p.array.begin(), p.array.end(), array.begin()); 
    }
    auto inline copy( T const (&p)[dim]) { 
        std::copy(std::begin(p), std::end(p), array.begin()); 
    }
    
  • 修正Point2D的拷贝构造函数,确保先初始化data再绑定引用:
    Point2D(Point2D const& o) : data(o.data), x(data.array[0]), y(data.array[1]){}
    

内容的提问来源于stack exchange,提问作者user6777901

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:37:06