Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding const& of temporary: No compiler warning?

I have a TestClass with a const& member variable. I know from various places and own experiences that it is a bad idea to initialize this const& with the reference to a temporary value. So I was quite suprised that the following code will compile fine (tested with gcc-4.9.1, clang-3.5, and scan-build-3.5) but fail to run properly.

class TestClass {
  public:
    // removing the "reference" would remove the temporary-problem
    const std::string &d;

    TestClass(const std::string &d)
        : d(d) {
        // "d" is a const-ref, cannot be changed at all... if it is assigned some
        // temporary value it is mangled up...
    }
};

int main() {

    // NOTE: the variable "d" is a
    // temporary, whose reference is not valid... what I don't get in the
    // moment: why does no compiler warn me?
    TestClass dut("d");

    // and printing what we got:
    std::cout << "beginning output:\n\n";
    // this will silently abort the program (gcc-4.9.1) or be empty
    // (clang-3.5) -- don't know whats going on here...
    std::cout << "dut.d: '" << dut.d << "'\n";
    std::cout << "\nthats it!\n";

    return 0;
}

Why does none of the two compilers warn me at compile-time? See also this ideone, with some more testing going on.

like image 220
user3520187 Avatar asked Dec 11 '14 12:12

user3520187


People also ask

What is a binding constant used for?

Binding constants provide a fundamental measure of the affinity of a solute to a ligand; hence the determination of binding constants has been an important step in describing and understanding molecular interactions. Many techniques have been developed to measure binding constants.

What is meant by affinity constant?

Definition. In chemistry and biochemistry, the affinity constant is the reciprocal of the dissociation constant, where both are equilibrium constants describing the strength of binding between a catalyst such as an enzyme or ribozyme and its substrate.

What does a higher binding constant mean?

The smaller the KD value, the greater the binding affinity of the ligand for its target. The larger the KD value, the more weakly the target molecule and ligand are attracted to and bind to one another.

How do you find the binding constant?

The binding constant can be calculated by dividing the on-rate by the off-rate, this is also equal to the concentration of ligand-molecule complex divided by the concentration of ligand times the concentration of the receptor molecule.


2 Answers

No warning as no offense:

local const references prolong the lifespan of the variable.

The standard specifies such behavior in §8.5.3/5, [dcl.init.ref], the section on initializers of reference declarations. The lifetime extension is not transitive through a function argument. §12.2/5 [class.temporary]:

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object to a subobject of which the temporary is bound persists for the lifetime of the reference except as specified below. A temporary bound to a reference member in a constructor’s ctor-initializer (§12.6.2 [class.base.init]) persists until the constructor exits. A temporary bound to a reference parameter in a function call (§5.2.2 [expr.call]) persists until the completion of the full expression containing the call.

You can have a look at gotw-88 for an extended and more readable discussion on this topic.

Undefined Behaviour

So is it your code correct? Nope, and its execution will lead to undefined behaviour. The real problem in your code snapshot is that the Undefined Behaviour is caused by the mix of two perfectly legal operations: the call of the constructor passing a temporary object (whose life spans inside the constructor block) and the binding of the reference in the constructor definition.

The compiler is not smart enough to detect this explosive statement combination, so this is why you don't get any warning.

like image 161
Alex Gidan Avatar answered Oct 25 '22 10:10

Alex Gidan


Binding a const & to a temporary is valid and the compiler will ensure that the temporary will live at least as long as the reference. This allows you to do things like pass string literals into functions expecting a const std::string &.

In your case however you are copying that reference and thus the lifetime guarantee no longer holds. Your constructor exits and the temporary is destroyed and you are left with a reference to invalid memory.

like image 35
sjdowling Avatar answered Oct 25 '22 11:10

sjdowling