fork(1) download
  1. #include <cstddef>
  2. #include <iostream>
  3. #include <vector>
  4.  
  5. class Field;
  6.  
  7. class Vector3d
  8. {
  9. // this is not really bad practice...
  10. // there can be valid reasons but you should really think twice
  11. // before declaring anything as a friend
  12. // in your case you are doing really bad things with it
  13. friend class Field;
  14.  
  15. public:
  16. // on its own this is not wrong
  17. // but in your case there are two issues:
  18. // 1. you want contigous memory, but the new creates these 3 doubles somewhere on the heap, not inside your object
  19. // 2. later on you will overwrite components_ with another pointer which makes this stuff leak
  20. Vector3d() : components_(new double[3]) {}
  21.  
  22. // see point 2 above: in the destructor components_ would be freed
  23. // while the addresses it points to are actually not freeable
  24. // EVEN WORSE: this is pseudo fixed in the Field destructor which sets all components_ to 0, so delete[] does nothing
  25. ~Vector3d() { delete[] components_; }
  26.  
  27. Vector3d(const Vector3d &v) : components_(new double[3])
  28. {
  29. components_[0] = v.components_[0];
  30. components_[1] = v.components_[1];
  31. components_[2] = v.components_[2];
  32. }
  33.  
  34. // usually one would overload the [] operator for this, but that is not a real issue
  35. // the const on the index is a bit useless here
  36. // speaking of which... you should overload the operator twice, because currently there is no const version of it
  37. double & operator()(const std::size_t index) { return components_[index]; }
  38.  
  39. // like so:
  40. // double operator()(std::size_t index) const { return componens_[index]; }
  41.  
  42. private:
  43. // I can see the intention for this constructor
  44. // and actually it would be a better approach then the stuff above
  45. Vector3d(double *ptr) : components_(ptr) {};
  46.  
  47. // I already suggested several methods to store the double's inline instead of on the heap
  48. double *components_;
  49. };
  50.  
  51. class Field
  52. {
  53. public:
  54. Field(std::size_t size);
  55. ~Field();
  56.  
  57. // again: useless const and no const version of the operator
  58. Vector3d & operator()(const std::size_t index) { return *(vectors_[index]); }
  59.  
  60. private:
  61. std::vector<double> components_;
  62. // what the actual fsck?
  63. std::vector<Vector3d *> vectors_;
  64. };
  65.  
  66. Field::Field(std::size_t size)
  67. : components_(std::vector<double>(3 * size)) // actually not that bad... but the context...
  68. , vectors_(std::vector<Vector3d *>(size, new Vector3d(0))) // wtf?
  69. {
  70. double *ptr = &components_[0];
  71. for (auto it = vectors_.begin(); it != vectors_.end(); ++it)
  72. {
  73. // seriosly?
  74. // the old memory allocated with new[] is totally screaming for its life here
  75. (*it)->components_ = ptr;
  76. ptr += 3;
  77. }
  78. }
  79.  
  80. Field::~Field()
  81. {
  82. for (auto it = vectors_.begin(); it != vectors_.end(); ++it)
  83. (*it)->components_ = 0; // what a dirty hack fix
  84. }
  85.  
  86. int main(int argc, char *argv[])
  87. {
  88. Field field(2);
  89. Vector3d &v = field(1);
  90. v(2) = 5;
  91.  
  92. Vector3d v2 = v;
  93. v2(2) = 2;
  94.  
  95. std::cout << field(1)(2) << std::endl;
  96.  
  97. return 0;
  98. }
Success #stdin #stdout 0s 3272KB
stdin
Standard input is empty
stdout
5