【问题标题】:can I make arithmetic expressions of vector objects?我可以制作矢量对象的算术表达式吗?
【发布时间】:2020-02-03 20:04:33
【问题描述】:

对于 3 向量类

template <typename T>
class vec3 {

   template <typename U>
   friend std::ostream& operator<<(std::ostream& out, const vec3<U>& v);

   template <typename U>
   friend std::istream& operator>>(std::istream& in, vec3<U>& v);

   protected:
   std::vector<T> data;

   public:
   vec3 (                    ): data(3)
        {}; // default constructor

   vec3 ( T x,   T y,   T z  ): data(3)
        { data[0] = x; data[1] = y; data[2] = z; } // constructor from 3 scalars

   vec3 ( T* xyz             ): data(3)
        { std::copy (xyz, xyz+3, data.begin() ); } // constructor from pointer

   vec3 ( const vec3<T>& rhs ): data(3)
        { std::copy ( rhs.data.begin(), rhs.data.end(), data.begin() ); } // copy constructor

   vec3<T> operator=( vec3<T> rhs ) {
        std::copy( rhs.data.begin(), rhs.data.end(), data.begin() ); // assignment    
        return (*this);
   }

   // passing on the [] operator for accessing elements
   T& operator[] ( size_t offset)       
         { return data[offset]; } // write access
   const T& operator[] ( size_t offset) const 
         { return data[offset]; } // read  access

   // left += and + for elements and vectors
   template <typename U>
   const vec3<T>& operator+= ( const U& rhs )       
         { data[0]+=rhs;    data[1]+=rhs;    data[2]+=rhs;    return (*this); }
   template <typename U>
   const vec3<T>& operator+= ( const vec3<U>& rhs ) 
         { data[0]+=rhs[0]; data[1]+=rhs[1]; data[2]+=rhs[2]; return (*this); }
   template <typename U>
   const vec3<T> operator+   ( const U& rhs )       
         { vec3<T> out(*this); out += rhs; return out;                        }

   // left *= and * for elements and vectors
   template <typename U>
   const vec3<T>& operator*= ( const U& rhs )       
         { data[0]*=rhs;    data[1]*=rhs;    data[2]*=rhs;    return (*this); }
   template <typename U>
   const vec3<T>& operator*= ( const vec3<U>& rhs ) 
         { data[0]*=rhs[0]; data[1]*=rhs[1]; data[2]*=rhs[2]; return (*this); }
   template <typename U>
   const vec3<T> operator*   ( const U& rhs )       
         { vec3<T> out(*this); out *= rhs; return out;                        }

   // rest of the operators

}

template <typename U>
std::ostream& operator<<(std::ostream& out, const vec3<U>& v)
   { return out << '(' << v.data[0] << ',' << v.data[1] << ',' << v.data[2] <<')'; }

template <typename U>
std::istream& operator>>(std::istream& in , vec3<U> &v)
   { return in >> v.data[0] >> v.data[1] >> v.data[2]; }

我尝试运行这段代码

float v[3] = { 10, 20, 30 };

vec3<float> v1 (v);
std::cout << v1 << " \n";
vec3<float> v2 (v1);
std::cout << v2 << " \n";
vec3<float> v3 = v2;
std::cout << v3 << " \n \n";

v3+=1.;
std::cout << v3 << " \n";
v3=v1+v2*2;
std::cout << v3 << " \n";

返回

(10,20,30) 
(10,20,30) 
(10,20,30) 

(11,21,31) 
Segmentation fault

所以我对复制构造函数、赋值有足够的信心,但是不可能将* 操作的结果传递给+ 吗?它返回一个const vec3&lt;T&gt; 那么这里出了什么问题?我猜是一些菜鸟的错误,但我没有看到。

【问题讨论】:

  • 通常,您会希望从 +=*= 运算符返回 T&amp; 而不是 const T&amp;。你应该花点时间阅读What are the basic rules and idioms for operator overloading?
  • 问题很可能出在您的 ctors 或作业中——您应该向他们展示(以及您的成员 vars)
  • 如果你的返回类型不是引用也不是指针,那么它不应该是const。在这些情况下,返回值 const 不会提供任何东西,而是禁用移动语义和优化。
  • 另外,为什么要对 3 个元素使用动态分配?为此目的,有std::array
  • :/ Godbolt 使用 gcc9.2。您将哪些选项传递给 gcc?您可以将代码发布到在线编译器并重现问题吗?我记得 CodeBlocks 有一个简单易用的调试器前端。

标签: c++ segmentation-fault operators pass-by-reference pass-by-value


【解决方案1】:
v3=v1+v2*2;

这一行递归调用函数

template <typename T, typename U>
inline vec3 <T> operator+ (U x, vec3 <T> y) {
    return y + x;
}

它在堆栈溢出后给出分段错误。 如果去掉这个函数,会调用成员函数const vec3&lt;T&gt; operator+ ( const U&amp; rhs )进行操作,它工作正常。

您应该将您定义的全局运算符函数添加到您的问题中。

【讨论】:

  • 我在问题中看不到y + x 方法?另外,我看不出这对 some 编译器来说是个问题。这是否是递归调用。是否取决于其他重载。
  • 在评论中 @alle_meije 将他的整个代码发布到 godbolt.org/z/Jz93y8。他没有在问题中发布该方法。对于 vec3 + vec3 操作,它需要调用 y + x 什么是 vec3 + vec3。它无休止地呼唤自己。
  • 谢谢!我没有将它放在原始帖子中,因为我没有将其视为问题的一部分......现在我看到这也涵盖了 U 是 vec3 的情况。我用它来涵盖许多要添加到向量中的标量类型。回到绘图板。
  • 删除typename U 然后为T x, vec3 &lt;T&gt; y 定义上面的内联函数是可行的。我曾尝试过在以前的版本中添加 intvec3 &lt;float&gt; 的案例。
猜你喜欢
  • 2020-12-17
  • 1970-01-01
  • 2018-06-22
  • 2011-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
相关资源
最近更新 更多