Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional assignment of references

Tags:

c++

gcc

Can someone with a deeper understanding of the C++ standard than me please elaborate on this?

This is my example program

#include <string>
#include <iostream>

int main(int argc, char* argv[]) {
    const std::string message("hello world");
    std::cout << std::hex << (void*)message.c_str() << std::endl;
    const std::string& toPrint = (argc > 0) ? message : "";
    std::cout << std::hex << (void*)toPrint.c_str() << std::endl;
    return 0;
}

On one machine it does this:

# g++ --version && g++ str_test.cpp && ./a.out                  
g++ (Debian 4.7.2-5) 4.7.2
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

0x9851014
0x9851014

message and toPrint seem to refer to the same instance as I would expect. However, on another machine, this happens:

# g++ --version && g++ str_test.cpp && ./a.out 
g++ (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

0x7ffeb9ab4ac0
0x7ffeb9ab4ae0

Here it looks like the compiler constructed a copy of message for toPrint to point at.

What behavior is correct according to the C++ standard? Or is it undefined in general?

like image 485
MBober Avatar asked Dec 25 '22 10:12

MBober


1 Answers

You are being confused by GLIBCs copy-on-write string sharing. Change your test program to:

#include <string>
#include <iostream>

int main(int argc, char* argv[]) {
    const std::string message("hello world");
    std::cout << std::hex << (void*)&message << std::endl;
    const std::string& toPrint = (argc > 0) ? message : "";
    std::cout << std::hex << (void*)&toPrint << std::endl;
    return 0;
}

(in other words print the address of the string object, not the address of the contained text), and both platforms will return different addresses.

The latest standard has forbidden copy-on-write (although I don't understand how exactly). Prior to that it was legal, but not mandatory. (Current thinking is that 'small string optimization' does better than cow - particularly in a multithreaded world).

like image 166
Martin Bonner supports Monica Avatar answered Jan 09 '23 13:01

Martin Bonner supports Monica