Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can "T t = {};" and "T t{};" produce different results?

The question is simple. Is it possible to construct such a type T, for which the following two variables declarations will produce different results?

T t1 = {};
T t2{};

I've been digging through the cppreference and the standard for more than an hour now, and I understood the following:

  • T t2{}; is a value initialization. No surprises here.
  • T t1 = {} is a list initialization with an empty braced-init-list.

But the last one is tricky since the "effects of list initialization" is an impressive... list. Which for classes, fundamental types and aggregates seems to boil down to value initialization. But I am not sure I haven't missed anything.

Maybe you can provide a context, in which the two declarations will have different effects?

UPD: Excellent answers about explicit constructors! Next level: is it possible that both statements compile, but have different effects on compile/run time?

like image 808
Mikhail Avatar asked May 25 '20 18:05

Mikhail


People also ask

Does JavaScript use pass by reference or value?

In JavaScript, all function arguments are always passed by value. It means that JavaScript copies the values of the variables into the function arguments. Any changes that you make to the arguments inside the function do not reflect the passing variables outside of the function.

Does TypeScript pass by reference or value?

The original variable won't change even if we change the argument variables that we passed in. Primitive data types like string, number, boolean, undefined and the null object is passed in by value in TypeScript.

Is JavaScript always pass by reference?

Yes, Javascript always passes by value, but in an array or object, the value is a reference to it, so you can 'change' the contents.

How Passing arguments works value vs reference JavaScript?

The difference between pass-by-reference and pass-by-value is, pass-by-value creates a new space in memory and makes a copy of a value, whereas pass-by-reference does not. Instead of making a copy, pass-by-reference does exactly what it sounds like; a value stored in memory gets referenced.


2 Answers

If you consider a case in which one statement will compile, but the other will not compile as "different effects," then yes, here's a context:

#include <iostream>

class T {
public:
    int data{ 0 };
    explicit T() {
        data = 0;
        std::cout << "Default constructor" << std::endl;
    }
};

int main()
{
    T t1 = {};
    T t2{};
    return 0;
}

The line declaring/initializing t1 gives the following, with clang-cl:

error : chosen constructor is explicit in copy-initialization

The MSVC compiler also complains:

error C2512: 'T': no appropriate default constructor available
message : Constructor for class 'T' is declared 'explicit'

like image 144
Adrian Mole Avatar answered Sep 19 '22 22:09

Adrian Mole


The difference is in explicit. I've managed to make msvc difference, but it looks like a compiler bug:

#include <iostream>
#include <initializer_list>

struct T
{
    template<class... A>
    T(A...) {std::cout << "1\n";}
    explicit T() { std::cout << "2\n"; }

};


int main()
{
    T t1 = {}; // 1
    T t2{}; // 2
}
like image 34
Alex Guteniev Avatar answered Sep 20 '22 22:09

Alex Guteniev