Search code examples
c++copy-constructorrvaluelvalue

An error occurred while constructing a 3D vector class


I'm debugging a 3D vector code, but I get the following error

/usr/bin/g++ -fdiagnostics-color=always -g /home/fangrui/vectorFEM/vectorFEM/main.cpp -o /home/fangrui/vectorFEM/vectorFEM/main
In file included from /home/fangrui/vectorFEM/vectorFEM/constant.h:6:0,
                 from /home/fangrui/vectorFEM/vectorFEM/mesh.h:2,
                 from /home/fangrui/vectorFEM/vectorFEM/edgenedelec.h:2,
                 from /home/fangrui/vectorFEM/vectorFEM/main.cpp:1:
/home/fangrui/vectorFEM/vectorFEM/cvector3D.h: In function ‘cvector operator*(double, cvector)’:
/home/fangrui/vectorFEM/vectorFEM/cvector3D.h:39:10: error: cannot bind non-const lvalue reference of type ‘cvector&’ to an rvalue of type ‘cvector’
   return cvector(x1*x2.x, x1*x2.y, x1*x2.z); 
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
...

It's a problem in cvector3D.h file, but I don't understand this bug and what kind of changes should be made. In addition to the error above, there is also a warning about friend:

class "cvector" has no suitable copy constructorC/C++(334)

here is the original code for cvector3D.h

# ifndef CVECTOR3D_H
# define CVECTOR3D_H

#include<cmath>
#include<ostream>
#include<iomanip>
using namespace std;

/*A three-dimensional real vector class is defined to facilitate numerical calculations*/
class cvector
{
public:
    double x, y, z;
    //Construct function
    cvector(double _x, double _y, double _z){ x = _x; y = _y; z = _z; } 
    //Copy the constructor
    cvector(cvector &pt){ x = pt.x; y = pt.y; z = pt.z; }
    cvector(){ x = 0; y = 0; z = 0; }
    ~cvector(){};

    //Operator overloading
    cvector operator +();
    cvector operator -();                   //The vector is negated

    friend  ostream  &operator<<(ostream &os, const cvector &x1);

    cvector operator +(cvector x1);
    cvector operator -(cvector x1);
    cvector operator *(double x1);
    cvector operator /(double x1);
    cvector &operator =(cvector x1);
    cvector &operator +=(cvector x1);
    cvector &operator -=(cvector x1);
    cvector &operator *=(double x1);
    cvector &operator /=(double x1);
    int operator ==(cvector x1);
    int operator !=(cvector x1);
    friend cvector operator *(double x1, cvector x2) {
        return cvector(x1*x2.x, x1*x2.y, x1*x2.z); 
    }
    //Member functions
    double  dist(cvector x1);                       
    cvector unit();                               
    double  norm();                           
    friend cvector cross(cvector x1, cvector x2)       
    {
        return cvector(x1.y*x2.z - x1.z*x2.y, x1.z*x2.x - x1.x*x2.z, x1.x*x2.y - x1.y*x2.x);
    }
    friend double dot(cvector x1, cvector x2)      
    {
        return (x1.x*x2.x + x1.y*x2.y + x1.z*x2.z);
    }
} ;

# endif

Solution

  • The cvector copy constructor is malformed.

    The correct form is cvector(const cvector& cvec).

    Long Description:

    When the friend function

    friend cvector operator *(double x1, cvector x2) {
            return cvector(x1*x2.x, x1*x2.y, x1*x2.z); 
        }
    

    is called the construnctor of cvector is called. Immediatly after the constructed object is returned by copy, so the copy constructor is called, but the lvalue just created of type cvector&, that is non-const cannot be converted to an rvalue of type cvector.

    This because a non-const reference parameter, such as for example an int&, can only refer to an "lvalue," which is a named variable.

    In this case the object created is not a named variable.