Are temporary objects in C++ const indeed?

2019-02-14 14:04发布

问题:

I always believed that temporary objects in C++ are automatically considered as const by the compiler. But recently I experienced that the following example of code:

function_returning_object().some_non_const_method();

is valid for C++ compiler. And it makes me wonder - are temporary objects in C++ const indeed? If yes, then why the code above is considered correct by the compiler?

回答1:

No, they're not. Not unless you declare the return type as const.



回答2:

It depends.

int f();
const int g();

class C { };
C x();
const C y();

In the case of both f() and g(), the returned value is not const because there are no const-qualified rvalues of non-class type. The const in the return type of g() is completely useless (in fact, it's worse than useless, since it can in rare circumstances cause issues with template instantiation).

In the case of x(), the returned value is not const (because it isn't const-qualified). In the case of y(), the returned value is const (because the return type is const-qualified). The const qualifier here (or lack thereof) is meaningful because the return type is a class type.



回答3:

Answering the question first, they are not actually const. You may not bind one to a non-const reference. This was probably done to prevent errors in certain situations where they would be passed as a parameter to a function that modifies them, only for the changes to be made to a temporary object and not the intended target.

Allowing non-const operations on a temporary is especially useful when you wish to call "swap" on it with a local variable.

std::vector<T> local;
method_that_returns_a_vector().swap( local );

Before the days of move semantics, this was considered the most efficient way to return a large data set and acquire it without copying all the data.



回答4:

Temporary objects can be const, but they don't have to be.

((string const)"hello").append(" world"); // error!

It allows for various things. Consider

struct bitref {
  int index;
  bitref &operator=(bool value); // non-const!
};

struct bitset {
  int flags;
  // returns a bitref temporary that's associated with the bit
  // at index 'index'. 
  bitref operator[](int index); 
  // ...
};

You could do

bitset b;
b[1] = true; // change second bit to 1

This is what's done by the std::bitset<> template.



回答5:

Temporary objects aren't const, but they can only bind to const lvalue references. It's easy to demonstrate that allowing temporaries to bind to non-const lvalue references would be bade in virtually all scenarios. You also can't take the address of a temporary, even though you can bind a reference to it, and a number of other very silly things happen with regards to temporaries in C++03. Just be glad that C++0x will be here soon... hopefully.



回答6:

It all depends on the return type of the function.

//Temporary objects: nameless objects that are only usable in current statement
Object function();           //Return a temporary object by value (using copy constructor)
const Object function();     //Return a const temp object by value

//references, return a reference to an object existing somewhere else in memory
Object & function();         //Return an object reference, non-const behaves as any other non-const
const Object & functon();    //Return const obj reference, behaves as any other const