C++ const std::shared_ptr<;常数T>;函数的参数最终更改智能指针中类的值

C++ const std::shared_ptr<;常数T>;函数的参数最终更改智能指针中类的值,c++,templates,inheritance,smart-pointers,C++,Templates,Inheritance,Smart Pointers,我在开发一个小代码时遇到了一些问题。它本质上是一个几何库,我为3D点定义一个类,为3D曲面定义一个抽象类,然后实现不同的曲面(平面、圆锥体…)。该库内置于模板中(必须如此,我才能在中使用它)。问题是: 点h #ifndef POINT_H #define POINT_H #include <iostream> #include <memory> template <typename T, int n> class Surface; template &l

我在开发一个小代码时遇到了一些问题。它本质上是一个几何库,我为3D点定义一个类,为3D曲面定义一个抽象类,然后实现不同的曲面(平面、圆锥体…)。该库内置于模板中(必须如此,我才能在中使用它)。问题是:

点h

#ifndef POINT_H
#define POINT_H

#include <iostream>
#include <memory>

template <typename T, int n>
class Surface;

template <typename T>
class Point
{
public:
  typedef std::shared_ptr<Point<T>> Ptr;
  typedef std::shared_ptr<const Point<T>> ConstPtr;
  Point(T&& x, T&& y, T&& z)
  {
    data_[0] = x;
    data_[1] = y;
    data_[2] = z;
    std::cout << "Point constructor" << std::endl;
  }
  Point(const T* data)
  {
    std::cout << "Cosntructor point from data ptr" << std::endl;
    for (size_t i = 0; i < 4; i++)
      data_[i] = data[i];
  }
  Point(const Point<T>& other) : Point(other.data_)
  {
    std::cout << "Constructor copy point" << std::endl;
  }

  ~Point()
  {
    std::cout << "Point destructor" << std::endl;
  }

  template <int n>
  T distance(const std::shared_ptr<const Surface<T, n>> surface) const
  {
    std::cout << "\n1: " << *this << std::endl;
    ConstPtr a(this);
    std::cout << "2: " << *this << std::endl;
    T d = surface->distance(a);
    std::cout << "3: " << *this << std::endl;
    return d;
  }

  T& operator[](size_t i)
  {
    return data_[i];
  }

  T operator[](size_t i) const
  {
    return data_[i];
  }

  T& x()
  {
    std::cout << "x&" << std::endl;
    return data_[0];
  }

  T& y()
  {
    return data_[1];
  }

  T& z()
  {
    return data_[2];
  }

  T x() const
  {
    return data_[0];
  }

  T y() const
  {
    return data_[1];
  }

  T z() const
  {
    return data_[2];
  }

private:
  T data_[3];
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Point<T>& point)
{
  os << "[";
  for (size_t i = 0; i < 3; i++)
  {
    if (i != 0)
    {
      os << ",";
    }
    os << point[i];
  }
  os << "]";
  return os;
}

#endif  // POINT_H
#ifndef SURFACE_H
#define SURFACE_H

#include <iostream>
#include <memory>

template <typename T>
class Point;

template <typename T, int n>
class Surface
{
public:
  typedef std::shared_ptr<Surface<T, n>> Ptr;
  typedef std::shared_ptr<const Surface<T, n>> ConstPtr;
  Surface()
  {
    std::cout << "Surface constructor" << std::endl;
  }
  virtual ~Surface()
  {
    std::cout << "Surface destructor" << std::endl;
  }
  virtual T distance(const std::shared_ptr<const Point<T>> point) const = 0;

  T& operator[](size_t i)
  {
    return data_[i];
  }

  T operator[](size_t i) const
  {
    return data_[i];
  }

protected:
  T data_[n];
};

#endif  // SURFACE_H
#ifndef PLANE_H
#define PLANE_H
#include "surface.h"

#include <math.h>

template <typename T>
class Point;

template <typename T>
class Plane : public virtual Surface<T, 4>
{
public:
  typedef std::shared_ptr<Plane<T>> Ptr;
  typedef std::shared_ptr<const Plane<T>> ConstPtr;
  using Surface<T, 4>::data_;
  Plane(T&& nx, T&& ny, T&& nz, T&& d)
  {
    data_[0] = nx;
    data_[1] = ny;
    data_[2] = nz;
    data_[3] = d;
    std::cout << "Plane constructor" << std::endl;
  }
  Plane(const T* data)
  {
    std::cout << "Cosntructor plane from data ptr" << std::endl;
    for (size_t i = 0; i < 4; i++)
      data_[i] = data[i];
  }
  Plane(const Plane<T>& other) : Plane(other.data_)
  {
    std::cout << "Constructor copy plane" << std::endl;
  }
  virtual ~Plane()
  {
    std::cout << "Plane destructor" << std::endl;
  }

  virtual T distance(const std::shared_ptr<const Point<T>> point) const override
  {
    return (data_[0] * point->x() + data_[1] * point->y() + data_[2] * point->z() - data_[3]) /
           sqrt(pow(data_[0], 2) + pow(data_[1], 2) + pow(data_[2], 2));
  }
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Plane<T>& plane)
{
  os << plane[0] << "*x+" << plane[1] << "*y+" << plane[2] << "*z = " << plane[3];
  return os;
}

#endif  // PLANE_H

问题在于
constptra(这一点)-此行创建一个
std::shared_ptr
,它拥有当前对象的所有权,并在对象超出范围后将其删除。
因此,
指针在调用
float d2=点->距离(平面)后变成悬空指针和取消引用它会导致未定义的行为


为了解决这个问题,
类需要继承自和行
ConstPtr a(this)需要变成
ConstPtr a(从_this()共享)

问题在于
ConstPtr a(此)-此行创建一个
std::shared_ptr
,它拥有当前对象的所有权,并在对象超出范围后将其删除。
因此,
指针在调用
float d2=点->距离(平面)后变成悬空指针和取消引用它会导致未定义的行为


为了解决这个问题,
类需要继承自和行
ConstPtr a(this)需要变成
ConstPtr a(从_this()共享)

如果代码中的任何地方都有未定义的行为,则所有赌注都将被取消,这是可能的。当面对某个变量的更改时(我并不期望),我只需让调试器在该变量上设置一个硬件监视,几秒钟后调试器就会告诉我错误所在。您是否尝试过使用调试器来分析此代码,如果没有,原因是什么
不创建新实例,并且不知道该对象已由另一个
共享的\u ptr
管理。你应该去看看,你能给我解释一下吗,或者给我指一个教程,在那里我可以看到这个?我在QtCreator中使用了调试器,但我只知道我的
分段错误在哪里。通过搜索谷歌,你会找到许多使用调试器的教程。在stackoverflow.com上,询问软件或教程建议是不合适的。您也可以阅读gdb的手册页。@UnholySheep解决了它!如果你将其发布为并回答,你将被接受!如果代码中的任何地方都有未定义的行为,那么所有的赌注都是无效的,这是可能的。当面对某个变量的更改时(我并不期望),我只需让调试器在该变量上设置一个硬件监视,几秒钟后调试器就会告诉我错误所在。您是否尝试过使用调试器来分析此代码,如果没有,原因是什么
不创建新实例,并且不知道该对象已由另一个
共享的\u ptr
管理。你应该去看看,你能给我解释一下吗,或者给我指一个教程,在那里我可以看到这个?我在QtCreator中使用了调试器,但我只知道我的
分段错误在哪里。通过搜索谷歌,你会找到许多使用调试器的教程。在stackoverflow.com上,询问软件或教程建议是不合适的。您也可以阅读gdb的手册页。@UnholySheep解决了它!如果你将其发布为并回答,你将被接受!
#include "plane.h"
#include "point.h"
int main()
{
  Point<float>::Ptr point(new Point<float>(100, 100, 1.6));
  Plane<float>::Ptr plane(new Plane<float>(1, 2, 3, -10));
  float d1 = plane->distance(point);
  std::cout << "Distance from " << *point << " to " << *plane << " -> " << d1 << std::endl;
  std::cout << "Point " << *point << "; Plane " << *plane << std::endl;
  float d2 = point->distance<4>(plane);
  std::cout << "Distance from " << *point << " to " << *plane << " -> " << d2 << std::endl;
  std::cout << "Point " << *point << "; Plane " << *plane << std::endl;
  return 0;
}
Point constructor
Surface constructor
Plane constructor
Distance from [100,100,1.6] to 1*x+2*y+3*z = -10 -> 84.1338
Point [100,100,1.6]; Plane 1*x+2*y+3*z = -10
1: [100,100,1.6]
2: [100,100,1.6]
3: [100,100,1.6]
Point destructor
Distance from [0,0,1.6] to 1*x+2*y+3*z = -10 -> 84.1338
Point [0,0,1.6]; Plane 1*x+2*y+3*z = -10
Plane destructor
Surface destructor
Point destructor