3

In my code, I used inner-class as an iterator for another class.

To simplify the situation, the code can be shown as follows:

class A {
public:
    class B {
    public:
        explicit B(void):idx(3){}
        B(const B&b)  {
            idx = 4;    // never be called
        }
    private:
        int idx=0;
    };
    B getB()
    {   return A::B();   }
};
void test2(){
    A a;
    A::B b = a.getB();  // b.idx ends with value of 3
}

The problem is that, in test2() , while running A::B b = a.getB();, the copy-constructor method wasn't called. And the b ends with value 3. Why is this?

For another problem confused me

class A {
public:
    class B {
    public:
        explicit B(void):idx(3){}
        explicit B(const B&b) {}  // C2440, cannot convert from "A::B" to "A::B"
    private:
        int idx=0;
    };
    B getB()
    {   return A::B();  }
};

Why will C2440 ocurrs with two types exactly the same?

Laine
  • 179
  • 1
  • 8
  • I'm not sure of the implication of making the copy constructor explicit but I wouldn't be surprised if it was the cause the problem. Try removing it. – François Andrieux Jun 04 '19 at 11:00
  • 1
    `explicit` only makes sense on converting constructors - informally, constructors that take one parameter of a type different from the class they construct. It serves no useful purpose on default or copy constructors and, as you've noticed, may cause mysterious problems. – molbdnilo Jun 04 '19 at 11:01
  • This post asks two questions, that should have been separate posts. The first question is a duplicate of https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization. – 1201ProgramAlarm Jun 04 '19 at 13:49

2 Answers2

8

What you are seeing is copy elision. In order to make it easier for optimizers to speed up the generated code, the C++ standard allows copy constructors to be skipped in certain situations.

Richard K. Wade
  • 299
  • 1
  • 5
  • 1
    Note, that since C++17 there it is no longer a "Copy Elision", since there is nothing to copy/be elided to begin with, due to the new rules regarding value materialization. It's explained further in your link. – Dan M. Jun 04 '19 at 11:30
4

C++ language does not guarantee the side effects of copy (nor of move) constructors to be observable in the abstract machine. This non-guarantee lets the compiler avoid temporary objects when they are not necessary, thereby avoiding copying of those objects in the concrete machine.

Your program relies on the side effects of a copy constructor. This is bad; Don't do it.

eerorika
  • 232,697
  • 12
  • 197
  • 326