1

I had a case where, due to an error in refactoring, a colleague introduced a bug similar to this code:

using namespace std;

int main()
{
    std::string s = s; // using s to initialize itself is fine?
    std::cout << s << std::endl;
    return 0;
}

The code compiles fine and only generates a warning in clang. The commented line should be equivalent to calling the constructor string::string(s) for s with an object whose constructor is not yet called. What's the use of this, why is it allowed by the language?

Alex
  • 7,728
  • 3
  • 35
  • 62
  • 2
    It's pretty much allowed by implication and because no wording in the language explicitly disallows it. In essence, the exact wording makes it legal by accident and it's probably not worth adding to the language to disallow it. There are rare cases where it's not UB but still not likely to be useful like `void * v = &v;` but in general it's not very useful. – François Andrieux May 28 '19 at 15:03
  • 1
    Also see [this](https://stackoverflow.com/questions/33649370/can-initializing-expression-use-the-variable-itself) on why the code UB – NathanOliver May 28 '19 at 15:06
  • I don't think the question is a duplicate because the other question just asks what happens, doesn't say _why_ it happens, and that's the part that I'm interested in. @FrançoisAndrieux your answer, although boring, does put my mind at ease (the committee simply didn't consider it, well, it happens). The implications of this seem to be that you can get around a private default constructor by using the copy constructor `string s = string(s);`, which is quite odd... – Alex May 28 '19 at 15:17
  • 1
    @Alex It doesn't really get around private constructors because it's certainly UB (unless the copy constructor is *very* weird or if the type has no data members at all). It's no more a workaround than using `reinterpret_cast` to "get an instance" from an array of bytes. They are both UB and they will almost certainly not do what you expect. It could get around private constructors for tag types though, for example. But the language's safety systems are designed to protect against accidents, not against sabotage. – François Andrieux May 28 '19 at 15:19
  • @Alex I added another duplicate whose answer contains a link to a defect report about this. – François Andrieux May 28 '19 at 15:22
  • I think the fact that it may or may not be UB depending on the _implementation_ of the copy constructor is disturbing enough. – Alex May 28 '19 at 15:22
  • @Alex Yes, it's very weird. Best to just assume it's always UB and not use it. It's very unlikely you can do something useful with this. And even if you can, you likely don't want to. It will just lead to confusion for the next people who have to read through that code. – François Andrieux May 28 '19 at 15:23

0 Answers0