我创建了一个包含3个参数的Vector类,并重载了-=操作符。
template <class T>
class Static3Vector
{
public:
Static3Vector() : m_coords{ 0, 0, 0 } {}
Static3Vector(T x, T y, T z) : m_coords{ x, y, z } {}
T operator [] (const size_t& i) { return m_coords[i]; }
T operator [] (const size_t& i) const { return m_coords[i]; }
Static3Vector operator -= (const Static3Vector& rhs)
{
for (int i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++)
this[i] -= rhs[i];
return *this;
}
private:
T m_coords[3];
};
但当我尝试使用这个操作符时
Static3Vector<int> vec1(1,2,3);
Static3Vector<int> vec2(1,2,3);
vec1 -= vec2;
我得到了我在标题中打出的错误。
this
是一个指针,而 this[i]
并非如你所愿。它需要 this
并执行指针运算。的唯一值 i
那么,不属于UB的 0
而这个表达式的类型是 Static3Vector<T>
和这个差不多。
Static3Vector<int> vec1(1,2,3);
Static3Vector<int>* ptr = &vec1;
ptr[0]; //ok, equivalent to *ptr
ptr[1]; //compiles, but invokes UB
你可以用几种方法来解决这个问题
(*this)[i] -= rhs[i]; //dereference first
this->operator[](i) -= rhs[i]; //call operator explicitly
m_coords[i] -= rhs[i]; //don't use overloaded operator, use data directly
还有一点,前两种方法在你目前的实现中是行不通的 operator[]
返回其存储值的副本。更典型的是 operator[]
返回对存储对象的引用。
T& operator [] (const size_t& i) { return m_coords[i]; }
const T& operator [] (const size_t& i) const { return m_coords[i]; }
看看你的索引操作符吧。
T operator [] (const size_t& i) { return m_coords[i]; }
T operator [] (const size_t& i) const { return m_coords[i]; }
它们之间唯一的区别就是一个是针对常量对象调用的,这就引出了一个问题,为什么你要重复它们。
不过这很容易回答:两个都应该返回引用,后者是 const
-限定,以避免复制,允许修改第一个。
修正这个问题是解决你的错误的第一步。
第二步,认识到 this
在参考文献出现之前,就已经引入了,因此是一个。指针 到实例,而不是一个 参考因此 this[n]
是指针运算,而不是调用你自定义的索引运算器。值得庆幸的是,这将导致不同的类型,从而导致过载解析失败。
下标操作符的使用不正确。在运算符的定义中,比如在这个
Static3Vector operator -= (const Static3Vector& rhs)
{
for (size_t i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++)
this[i] -= rhs[i];
return *this;
}
在此声明中
this[i] -= rhs[i];
对于一个指针类型的对象,使用了b内置的下标操作符。Static3Vector *
.
你需要写
( * this )[i] -= rhs[i];
或
this->operator[]( i ) -= rhs[i];
同时,返回类型应是一个引用类型,如
T & operator [] (const size_t& i) { return m_coords[i]; }
const T & operator [] (const size_t& i) const { return m_coords[i]; }
和
Static3Vector & operator -= (const Static3Vector& rhs)
{
for (size_t i = 0; i < sizeof(m_coords) / sizeof(m_coords[0]); i++)
( *this )[i] -= rhs[i];
return *this;
}