-5

In Visual Studio 2019, I am trying, without success, to implement the technique for making a class non-copyable shown for C++11, and later, at the accepted answer at How do I make this C++ object non-copyable?.

My class is,

class Foo {

public:
    Foo();
    Foo(std::string name);
    ~Foo();

    std::string m_name;

    static std::int32_t s_counter;

public:
    Foo(const Foo& inFoo) = delete;
    Foo& operator=(const Foo& inFoo) = delete;
};

The definition code is,

std::int32_t Foo::s_counter = 0;

Foo::Foo(void)
{
    Foo::s_counter++;
    std::cout << "Foo constructor.  Count = " << Foo::s_counter << std::endl;
}

Foo::Foo(std::string name)
{
    Foo::s_counter++;
    m_name = name;
    std::cout << "Foo " << m_name << " constructor.  Count = " << Foo::s_counter << std::endl;
}

Foo::~Foo()
{
    Foo::s_counter--;
    std::cout << "Foo destructor.  Count = " << Foo::s_counter << std::endl;
}

It is used in,

int main(int argc, char** argv) {

    std::vector<Foo> fooVector;

    {
        Foo myFoo1{ Foo() };
        fooVector.push_back(std::move(myFoo1));

        Foo myFoo2{ Foo("myFoo2") };
        fooVector.push_back(std::move(myFoo2));
    }

    if (Foo::s_counter < 0) {

        std::cout << "Foo object count = " << Foo::s_counter << std::endl;
    }

    std::cin.get();
}

in which I have intentionally scoped the definition of myFoo1 and myFoo2 so as to get object count feedback.

When the copy constructor and assignment constructor are made public, as shown, the compile error is "C2280 'Foo::Foo(const Foo &)': attempting to reference a deleted function". When they are made private, the compile error is "C2248 'Foo::Foo': cannot access private member declared in class 'Foo'".

I believe I am misinterpreting something in the original SO answer, but I cannot see what it is.

user34299
  • 377
  • 2
  • 11
  • 8
    I don't get it. You've tried to make the object non-copyable. Then you tested it by attempting a copy. The copy failed, as desired. Then you tried a different approach. Success again. What's the problem/question? – Lightness Races in Orbit Jan 09 '20 at 01:26
  • 4
    Those errors are the expected result of trying to copy a non-copyable class. – Retired Ninja Jan 09 '20 at 01:31
  • 2
    Don't forget that what you're seeing is, by definition, (usually), correct. So by extension it's what we're all expecting. So, if you were expecting something else instead, you're going to have to tell us what that is. Only then can we tell you why your expectation is wrong. – Lightness Races in Orbit Jan 09 '20 at 01:33
  • Can you explain your use of `std::move`? Your class is not movable. In case it is not clear, the error message comes from the `push_back` line which attempts to copy the object into the vector. (the other comments/answers seem to have overlooked this) – M.M Jan 09 '20 at 01:50
  • 1
    It would improve the question to show the full error message which will make it apparent which line caused the error – M.M Jan 09 '20 at 01:56
  • 1
    BTW it is simpler to use `fooVector.emplace_back();` and `fooVector.emplace_back("myFoo2");` if the intent is to get objects in the vector – M.M Jan 09 '20 at 01:59

1 Answers1

6

Everything's working as expected.

Your code attempts two copies, and both approaches you took to making the class non-copyable succeeded. You can see that, because you got compilation errors.

If you didn't intend to attempt copies in this testcase, it could be these lines:

Foo myFoo1{ Foo() };
Foo myFoo2{ Foo("myFoo2") };

Prior to C++17, those were copy-initialisations. If that's not what you intended, and you're pre-C++17, then you should change them to:

Foo myFoo1{};
Foo myFoo2{"myFoo2"};

… or a good old-fashioned:

Foo myFoo1;
Foo myFoo2("myFoo2");

Meanwhile, your push_backs definitely copy because, though you wrote std::move, your class isn't moveable (has no move constructor) so the std::move actually does nothing.

So:

  1. Attempt to copy object
  2. Copy is being prevented

All as it should be.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • since C++17 `Foo myFoo1{ Foo() };` is exactly identical to `Foo myFoo1{};`, and similarly for the `myFoo2` line, so those suggestions would make no difference – M.M Jan 09 '20 at 01:52
  • Isn't `std::move()` as part of the `push_back()` argument supposed to prevent a copy from being created, and merely move the object into the `std::vector`? If that is not the case, then I do not understand the reason for `std::move()` use in the recommendation in the referred to answer. – user34299 Jan 09 '20 at 02:00
  • The problem I am having is that more `Foo` objects are being deleted than constructed, i.e., `Foo::s_counter` is negative just before `main()` exits. – user34299 Jan 09 '20 at 02:02
  • @user34299 No, that is a common misconception. `std::move` just makes the name of a variable into an rvalue, so that it can bind to the rvalue ref argument in a move constructor. In other words, it "makes it possible to move". It doesn't actually move anything. Indeed, how could it? You did not specify any instructions for moving in your class. Should review move semantics in your book. – Lightness Races in Orbit Jan 09 '20 at 02:03
  • @user34299 _"The problem I am having is that more Foo objects are being deleted than constructed, i.e., Foo::s_counter is negative just before main() exits"_ Your question didn't say anything about this at all – Lightness Races in Orbit Jan 09 '20 at 02:03
  • @user34299 There is no `std::move` mentioned in the other question you refer to (which is to be expected, since it is from 2010 , before move semantics were added to the language) – M.M Jan 09 '20 at 02:03
  • And that. `std::move` is not found on that entire page even once.... – Lightness Races in Orbit Jan 09 '20 at 02:04
  • I do not know what semantics to review. I was following the example in the referred to post and am trying to understand it with my own code, without success. – user34299 Jan 09 '20 at 02:05
  • I just told you! Read the relevant chapter about move semantics in your book. – Lightness Races in Orbit Jan 09 '20 at 02:05
  • 1
    @user34299 you say "I do not understand the reason for std::move() use in the recommendation in the referred to answer." but the referred to answer does not recommend std::move or even mention it at all , you are making no sense – M.M Jan 09 '20 at 02:05
  • What relevant chapter in what book? – user34299 Jan 09 '20 at 02:06
  • 4
    Okay I think we're being taken for a bit of a ride. I'm out... – Lightness Races in Orbit Jan 09 '20 at 02:07