Is a const int ref in a constructor safe to bind to a literal?


Ryan Haining

I know the standard has an exception for extending the lifetime of temporary objects, which basically says that binding a const reference in a constructor doesn't extend the lifetime, but does that apply to literals as well? E.g:

class C {
    private:
        const int& ref;
    public:
        C(const int& in)
            : ref{in}
        { }
};

If I have a function that returns an object of this type

C f() {
    C c(2);
    return c;
}

Will the value c.refin the caller be undefined if I know it must be literal?

Columbus

No. _ You can't use the reference after the constructor has finished executing. A temporary class is always introduced when
a prvalue of a non-class type is bound to a -reference of the constsame type . So the parameter reference of the constructor will refer to a temporary object which will be destroyed once the reference goes out of scope. After that, the member reference is dangling, and attempts to access the stored value behind that reference will result in UB. [dcl.init.ref]/5:

The reference input " CV1 T1 " is initialized by an expression of type " CV2 T2 " as follows:

  • If the reference is an lvalue reference and an initializer expression
    • is an lvalue (but not a bitfield), and [..]
    • has a class type (ie, T2is a class type) [..]
  • Otherwise, the reference shall be an lvalue reference to a non-volatile consttype (i.e. cv1 is const), or the reference shall be an rvalue reference.

    • if the initializer expression

      • is an xvalue (but not a bitfield), class prvalue, array prvalue or function lvalue and [..]
      • has class type [..]
    • Otherwise: (5.2.2.1)

      • If T1the class type [..]
      • If T1of non-class type, a temporary of type " cv1 " is created and copy-initialized from the initializer expression (8.5). Then bind the reference to the temporary directory.T1

Not surprisingly, integer literals are indeed prvalues. [expr.prim.general]/1:

String literals are lvalues; all other literals are prvalues.

Finally, [class.temporary]/5 if it's unclear:

A temporary object that references a bound temporary object or a complete object that references a bound child object persists for the lifetime of the reference, except in the following cases:

  • In the constructor's ctor-initializer (12.6.2), temporary bindings to reference members persist until the constructor exits.

Related


Is a const int ref in a constructor safe to bind to a literal?

Ryan Haining I know the standard has an exception for extending the lifetime of temporary objects, which basically says that binding a const reference in a constructor doesn't extend the lifetime, but does that apply to literals as well? E.g: class C { pri

Is a const int ref in a constructor safe to bind to a literal?

Ryan Haining I know the standard has an exception for extending the lifetime of temporary objects, which basically says that binding a const reference in a constructor doesn't extend the lifetime, but does that apply to literals as well? E.g: class C { pri

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Pass literal as const ref parameter

innocent bystander Imagine the following simplified code: #include <iostream> void foo(const int& x) { do_something_with(x); } int main() { foo(42); return 0; } (1) Besides optimization, what happens when 42 is passed to foo? Does the compiler stick 42 somew

Difference between const int and int literal

AND I'm trying to understand auto, but some questions confuse me. E.g: const int ci=0; auto &g=ci; auto &h=42; Why is the second line correct and the third line wrong? Ayman Al Eliani You cannot have references or pointers to r values. An r-value is a value t

C++ - Create safe const char* constructor

qiubit I'm creating a class with constructor initialization that const char*should safely construct an object using data provided in a buffer containing strings. My concern is that the user might NULLuse this constructor with the wrong data, e.g. a pointer or

How to initialize int const *const in constructor?

Yongjian Wang 经验。我有一个 class foo{ public: int const * const array; size_t const length; } 构造后这些变量不应该有任何变化,包括任何成员方法,但每个人都应该可以访问这些值,因此它们应该是常量。 但是在构造函数中,我需要先确定长度,然后才能初始化数组, 此外,我需要调用一个函数来分配内存位置,而不仅仅是一个new,因为这个类是一个巨大的不透明数据结构的桥梁,并且内存是由那个人管理的。(考虑诸如 v8

bind const T(&ref)[N] to an object of type T[N]

Ryan Haining I've noticed strange semantics when binding references to pointers and arrays that differ in terms of constness to point and array elements, respectively. With pointers, this fails predictably: int* p{}; const int*& p_ref{p}; non-const lvalue ref

Why vector<int> variable returned by const ref doesn't work

moth Here is my function: const vector<int>& getVInt(){ vector<int> vint; (...) return vint; } and, vector<int> x = getVInt(); return: Throwing 'std:: out_of_range' what(): terminate call after vector::_M_range_check instance and const vector<int>& x

Why can't the compiler bind a const int to an rvalue reference?

Bake ZQ Here is a subset of my code. Why can't a be bound const intto an rvalue reference? What I thought was that the type that Twould be deduced and the AS would be folded .int const &eint const & &&int const & template <typename T> List<T>::List(initializer

Why can't the compiler bind a const int to an rvalue reference?

Bake ZQ Here is a subset of my code. Why can't a be bound const intto an rvalue reference? What I thought was that the type that Twould be deduced and the AS would be folded .int const &eint const & &&int const & template <typename T> List<T>::List(initializer

Why can't the compiler bind a const int to an rvalue reference?

Bake ZQ Here is a subset of my code. Why can't a be bound const intto an rvalue reference? What I thought was that the type that Twould be deduced and the AS would be folded .int const &eint const & &&int const & template <typename T> List<T>::List(initializer