In a pre-C++17 compiler, this is known as copy elision (test it with C++17 on compiler explorer or wandbox with -std=c++17 vs. -std=c++14 flags).
As of C++17, the compiler must delete numerous instances of copy and move constructors and create objects directly without the need of intermediary objects.
Unlike
A a { 10 };
the line
A a = 10;
means that a temporary object is constructed first, as if the code has:
A a = A(10);
Until C++17, the compiler could optimise this code and create a straight from 10 without using a temporary object.
It should be noted that doing this copy elision optimization was permitted but not needed.
You've seen that this allowed for optimization.
Regardless matter whether it chose to conduct copy elision or not, the compiler had to compile or fail the code.
If the compiler was unable to invoke the copy function Object() { [native code] }, as in your example, it was forced to fail the compilation unconditionally, even if copy elision was chosen.
With C++17, the compiler is now required to perform the copy elision optimization in this scenario.
Because the copy function Object() { [native code] } is guaranteed to be elided, no copy function Object() { [native code] } is necessary, and the code can compile without problem.
Note the copy constructor without const:
A(A &other) { std::cout << " other " << std::endl; value = other.value; }
Without copy elision, this copy constructor can't be used for:
A a = A(10);
It can't be used because A(10) is a temporary object, and as such can be passed as an rvalue parameter to constructors and methods like
A(A && other);
foo(A && other);
or passed as a const lvalue reference parameter to constructors and methods like
A(const A& other);
bar(const A& other);
But it can't be passed as a regular mutable parameter (like in your code block 3).
With copy elision it does not even try to call the copy or the move constructor in these cases.
It still needs to call the copy constructor for
A b = a;
and it can do that with a mutable parameter, only because a is neither a temporary nor a const object. If you make a const then the code will fail to compile, when the copy constructor does not get a const (for C++17 and earlier):
const A a = 10;
A b = a;
// ^^ this will fail
Fun note: The following line will is guaranteed not to call the copy constructor even once with C++17:
A a = A(A(A(A(1))));