0

Recently I encountered a serious bug while working on a project. It took me a whole day to figure out what causes the bug. Turns out, there is "bad design "(should i say?) in one library that I use.

Let's assume that we have this foo class:

struct foo {
  inline foo(int& i) : i_(i) { }

  inline foo& operator=(const foo& that) {
    if (this != &that) {
      i_ = that.i_;
    }
    return *this;
  }

  inline
  friend std::ostream& operator<<(std::ostream& os, const foo& f) {
    os << f.i_;
    return os;
  }

  private:
    foo();
    int& i_;
};

And here is the sample use of foo:

#include <iostream>
#include <utility>


int main(int argc, char** argv) {
  int x = 10;
  int y = 100;

  foo f1(x);
  foo f2(y);

  std::cout << "before swapping" << std::endl;

  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl;
  std::cout << "f1 = " << f1 << std::endl;
  std::cout << "f2 = " << f2 << std::endl;

  std::swap(f1, f2);

  std::cout << "after swapping" << std::endl;

  std::cout << "x = " << x << std::endl;
  std::cout << "y = " << y << std::endl;
  std::cout << "f1 = " << f1 << std::endl;
  std::cout << "f2 = " << f2 << std::endl;

  return 0;
}

And result:

before swapping
x = 10
y = 100
f1 = 10
f2 = 100
after swapping
x = 100
y = 100
f1 = 100
f2 = 100

I apologize if someone has already posted this issue before, if that's the case, please let me know, I'll delete this post.

In case no one has ever mentioned/encountered this issue before, please allow me to bring it up, to:

  1. Ask if someone could come up with a solution to swap these two foo objects.

  2. To remind me/others that std::swap is not one-size-fits-all solution. So use it with caution!

Thank you!

Ngoc Linh
  • 9
  • 2
  • 3
    References can't be reassigned, so what do you want to do? – Rakete1111 May 31 '18 at 11:18
  • 2
    https://stackoverflow.com/questions/25804844/is-there-an-elegant-way-to-swap-references-in-c – Mat May 31 '18 at 11:19
  • @Rakete1111 the foo class above is the simplified version of one of the class in one library that I use. The idea is that, each foo is a view of an existing matrix column ( could be big) so in order to randomly shuffle these columns, I store these views in a vector and randomly shuffle this vector instead( much cheaper than shuffling the matrix itself). I guess i have to use another solution instead. Thank you! – Ngoc Linh May 31 '18 at 11:32
  • @Mat Thank you! – Ngoc Linh May 31 '18 at 11:32
  • You might use `struct foo { inline foo(int& i) : i_(&i) { } inline foo& operator=(const foo& that) { if (this != &that) { i_ = that.i_; /* pointer or pointed copy ?*/ } return *this; } inline friend std::ostream& operator<<(std::ostream& os, const foo& f) { os << f.i_; return os; } private: foo(); int* i_; };` – Jarod42 May 31 '18 at 12:10
  • This doesn't address the question, but you don't need those `inline`s; member functions that are defined inside the class definition are implicitly inline. – Pete Becker May 31 '18 at 16:25

0 Answers0