13

I recently ran into some weird bugs due to this kind of code.

vector<int> a(a);

Why the code above is accepted? When is this necessary? And how to ask the compiler to forbid this kind of usage? Thank you.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
mr.pppoe
  • 3,945
  • 1
  • 19
  • 23
  • 4
    Well, you can spot it by [the warning](http://coliru.stacked-crooked.com/a/b945fa62ce2957a9). Anyway, when you declare a variable, it's in scope right after its declaration, which incidentally includes its initialization. As an aside, there's a [cppquiz question](http://cppquiz.org/quiz/question/119) about this. – chris Feb 25 '14 at 03:37
  • I'd guess it's UB ... – πάντα ῥεῖ Feb 25 '14 at 03:37
  • @chris Whoah clang! Sadly, [GCC](http://coliru.stacked-crooked.com/a/d13b5d834d69310a) doesn't seem to think so even with the same compiler flags. – Mark Garcia Feb 25 '14 at 03:38
  • @MarkGarcia that disappointed me to. – Shafik Yaghmour Feb 25 '14 at 03:39
  • @MarkGarcia, That's odd. I could have sworn it did last I saw. For example, [here](http://coliru.stacked-crooked.com/a/034c74e2a694c17d). Oddly enough, `int i = i;` does not in either, so I'm not sure whether it's not actually UB or they just don't detect it. – chris Feb 25 '14 at 03:41
  • @chris: See http://stackoverflow.com/questions/14935722/does-initialization-entail-lvalue-to-rvalue-conversion-is-int-x-x-ub. In short the rhs is converted to a prvalue and since it is an uninitialized value it ub. – Jesse Good Feb 25 '14 at 03:59
  • @JesseGood, Oh geez, it's `&*p` and `&arr[size]` all over again. Still, thanks :) – chris Feb 25 '14 at 04:07
  • On MSVC13 the above will not compile: error C2065: 'a' : undeclared identifier. – jaho Feb 25 '14 at 04:10
  • @Marian, I think you mean MSVC12 (VS2013), but that's definitely wrong behaviour, as explained in the cppquiz link. `a` is available for use then for sure. – chris Feb 25 '14 at 04:13
  • @chris: UB in most cases need not be diagnosed by the compiler. And yes, it is undefined behavior in this case, as you are reading out of an uninitialized variable (to initialize itself) – David Rodríguez - dribeas Feb 25 '14 at 05:12

2 Answers2

6

The most common use case for that is actually in C, not C++ (you should not use malloc in C++, although you can), but in this case C++ is backwards compatible:

mytype *p = malloc(sizeof *p);

By allowing the use of p in the initializer expression, you can pass sizeof *p to malloc ensuring that whatever the size of mytype is, the right size will be allocated. If you were not allowed to do *p, then the expression above would have to have the type mytype twice, and later maintenance in the code might update one of the types and fail to update the other.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

This is an unusual construct to actually make use of, but it can be useful if a class has a constructor that takes a reference to some other object for some reason, and the caller may want to loop the object into its own initialization.

Here's a contrived example:

#include <iostream>
using namespace std;

struct PrintAnAddress {
    PrintAnAddress()
        : msg_("")
        , addr_(NULL)
    { }
    PrintAnAddress( char const *msg, PrintAnAddress const &that )
        : msg_( msg )
        , addr_( &that )
    { }
    void operator()( ostream &os ) const {
        cout << msg_ << addr_ << endl;
    }
private:
    char const *msg_;
    PrintAnAddress const *addr_;
};

int main() {
    PrintAnAddress p1;
    PrintAnAddress p2( "p1:", p1 );
    PrintAnAddress p3( "self:", p3 );
    p1(cout);
    p2(cout);
    p3(cout);
}

When p2 is defined, it's set up to print the address of p1, but when p3 is defined, it's set up to print its own address. If the p3 variable were not yet in scope, it would not be possible to refer to it in order to pass it in its initialization. (At least, not without instrumenting the class and somehow getting access to the this pointer.)

I'm sure there are useful and valid applications of this construct, but as I say, it's pretty unusual, so none come to my mind at the moment.

Adam H. Peterson
  • 4,511
  • 20
  • 28