-2

IDE - Visual Studio Express 2013 for Desktop

C++11

Problem - I have a class which is apparently being copied (using copy constructor). If I declare the copy constructor like this:

MyClass(const MyClass&) = delete;

It complains about a reference to a deleted function. I have gone over my entire code twice now and cannot find where an instance of the class would be copied.

Is there any way to find where the reference comes from?

I have tried defining the copy constructor, with a breakpoint in it, but it is never hit.

Update

Sorry it actually does show where the reference is - in some allocator in the STL. I managed to track it down to a std::vector::emplace_back() call - which must cause a copy. I will investigate this.

Update 2

I'm such a dumbass - I had a vector of MyClass...

brettwhiteman
  • 4,210
  • 2
  • 29
  • 38
  • 8
    That would be a compiler error, and any decent compiler would tell you exactly where the error is originating. – juanchopanza Jul 05 '14 at 09:33
  • 1
    Have you tried to clean and rebuild the project? – n. m. could be an AI Jul 05 '14 at 09:37
  • 1
    Search for `MyClass x=y`, `MyClass x(y)` and `MyClass* x = new MyClass(y)`. – barak manos Jul 05 '14 at 09:41
  • To increase your chances of getting a meaningful answer (and to avoid the downvotes), please post an http://www.sscce.org/ , and copy-paste the entire compiler error message you get. Even better if you enable all warnings, recompile, and then copy-paste all warnings as well. – pts Jul 05 '14 at 09:47
  • Oh, also check if you send to a function or return from a function a `MyClass` instance **by value**. I believe that the copy constructor is implicitly called in both cases, in order to replicate that instance on the stack. – barak manos Jul 05 '14 at 09:51
  • In addition, "I have tried defining the copy constructor, with a breakpoint in it, but it is never hit" - that doesn't prove anything, as it's a runtime issue, and the problem you're experiencing occurs during compilation. – barak manos Jul 05 '14 at 09:58
  • @barakmanos there is no need to search for anything. As I said in my first comment, it is a compiler error. I don't know much about VS, but I would expect that it would tell you where the error originates. – juanchopanza Jul 05 '14 at 10:05
  • @juanchopanza: Apparently not (if you consider VC 2013 a decent compiler, which I do) :) It seems to be a compiler bug acknowledged by MS, see my answer. – Christian Hackl Jul 05 '14 at 11:40
  • @ChristianHackl Wow, good catch. I did say *decent compiler* though :-) – juanchopanza Jul 05 '14 at 11:40

1 Answers1

3

Perhaps you have encountered the following compiler bug:

http://connect.microsoft.com/VisualStudio/feedback/details/889420/issue-with-delete

It says that the IDE (IntelliSense) complains while the compiler does not, which would explain why you have not posted any compiler error message and why you could actually execute a compiled program with breakpoints in the first place.

The bug itself is easy to reproduce:

struct Example
{
  Example() {}
  Example(Example const &) = delete;
};

Example f()
{
  return Example();
}

int main()
{
  Example e = f();
}

Compiled with VC 2013 like this:

cl /nologo /EHsc /W4 /Za stackoverflow.cpp

No error, no warning.

Now if you go to http://www.compileonline.com/compile_cpp11_online.php instead and compile the very same code with GCC 4.7.2, there are the expected compiler errors:

main.cpp: In function ‘Example f()’:
main.cpp:9:18: error: use of deleted function ‘Example::Example(const Example&)’
   return Example();
                  ^
main.cpp:4:3: error: declared here
   Example(Example const &) = delete;
   ^
main.cpp: In function ‘int main()’:
main.cpp:14:17: error: use of deleted function ‘Example::Example(const Example&)’
   Example e = f();
                 ^
main.cpp:4:3: error: declared here
   Example(Example const &) = delete;
   ^

So, you actually have two problems:

  1. Your compiler has a bug. This can only be solved by upgrading to a newer version if/when one is available.

  2. Your code invokes the copy constructor for a class which does not allow copying.

The second problem can be solved by considering the rules for when C++ copies an object "indirectly" -- or requires a copy constructor to be present even if the actual copying is optimised away. Inspect the code again looking for the following cases:

  • Pass by value. void f(MyClass obj);.
  • Return by value. MyClass f();.
  • Throwing. throw MyClass();

The first one is easily fixed:

void f(MyClass const &obj);

The others require a more thorough redesign, because returning or throwing directly contradicts the idea of preventing copies.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • I think the problem is more that somewhere in my code an explicit or implicit copy is being performed on MyClass. I want to remove this as I want MyClass to be 'uncopyable'. The problem is with finding the reference to the deleted function. – brettwhiteman Jul 05 '14 at 19:17
  • @Brett: What do you mean *more* that somewhere there is an explicit or implicit copy? That's exactly what I explained in the second half of my answer, where I gave examples of implicit copies. – Christian Hackl Jul 06 '14 at 10:43