3

I am not asking about the logic of such a call, rather I'm interested in a difference of support b/w Visual C++ and GCC / Clang. Visual C++ will not allow a new instance of an object to be used as the parameter for its own copy constructor. GCC and Clang allow this. Considering that 'int i = i;' is allowed, I'm wondering whether Visual C++ has a bug.

class test {
private:
    test() {}
public:
    test(const test& t) {}
};

int main(void) {
    int i = i;
    test t(t); -- this line gives an error in Visual C++
    return 0;
}
nachum
  • 567
  • 9
  • 17
  • 2
    So in GCC, does the chicken or the egg come first? – Jon Sep 22 '11 at 16:45
  • `int i = i` and `test t(t)` are rather different forms. The latter is very clearly invalid (really, the former should be as well). – ssube Sep 22 '11 at 16:45
  • 1
    int i = i is an assignment, no copy construction inoked there.. – stijn Sep 22 '11 at 16:46
  • 4
    @stijn: `int i=i` is not an assignment. – Nawaz Sep 22 '11 at 16:50
  • There is soooo much wrong with trying to do that... – riwalk Sep 22 '11 at 16:58
  • I'm curious (and I don't have MSVC handy). What happens with `int i2(i2);` and `test t2 = t2;`. – Robᵩ Sep 22 '11 at 17:00
  • @Stargazer712: in principle it could make sense, for example consider `struct node { node *pnext; explicit node(node &nextnode) : pnext(&nextnode) {} };`. Then `node loop(loop)` would create an infinite list (which might mean "empty" if your other list functions interpret it that way. Not so much for singly-linked, but for doubly-linked lists you get a couple of nice features from storing them as a ring, with the same "head" node at both ends). – Steve Jessop Sep 22 '11 at 17:12
  • @SteveJessop, I don't disagree with that, but there are probably clearer ways to do it (like in the default constructor). – riwalk Sep 22 '11 at 17:17
  • @Stargazer712: yeah, and to be honest it's probably not a good idea even for my constructor to take a reference. It should be a pointer, to make it clearer what the parameter is for. – Steve Jessop Sep 22 '11 at 17:50
  • @Nawaz please specify what it is then? – stijn Sep 22 '11 at 18:21
  • 1
    @stijn: It's called initialization; more precisly, *dynamic* initialization. See this : [What is dynamic intialization of object in c++?](http://stackoverflow.com/questions/5945897/what-is-dynamic-intialization-of-object-in-c) – Nawaz Sep 22 '11 at 18:23

2 Answers2

2

To quote the C++ standard (3.3.2):

The point of declaration for a name is immediately after its complete declarator and before its initializer

In your first statement, the declarator ends after int i, and so the name i is available where it's used in the initializer (= i), so the statement is well-formed, but its behaviour is not defined.

In your second statement, the declarator ends after test t(t), and there is no initializer; the name t is not available where you use it, so the statement is ill-formed.

So the compiler is behaving correctly. I would hope it could be configured to give a warning about the first statement, but it's not required to reject it; it is required to reject the second, as you say it does.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0
 test t(t); -- this line gives an error in Visual C++ 

Where have you defined t? The compiler is not physic!

Ed Heal
  • 59,252
  • 17
  • 87
  • 127