# C++ Quiz #1

DevFeed: [C++ Quiz #1](<https://devfeed.tech/articles/c-quiz-1-30808.md>)

Original publisher: [Read original article](<https://hookrace.net/blog/cpp-quiz-1/>)

Published: 2017-11-30T23:00:00Z

Content type: tutorial

Language: en

Sources: [Dennis Felsing](<https://devfeed.tech/sources/dennis-felsing.md>)

Topics: [C++](<https://devfeed.tech/topics/c-plus-plus.md>), [Parser](<https://devfeed.tech/topics/parser.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [c-plus-plus](<https://devfeed.tech/tags/c-plus-plus.md>), [code](<https://devfeed.tech/tags/code.md>), [constructor](<https://devfeed.tech/tags/constructor.md>), [parsing](<https://devfeed.tech/tags/parsing.md>), [programming](<https://devfeed.tech/tags/programming.md>)

## AI overview

This C++ tutorial examines how ambiguous parsing affects constructor expressions, temporary objects, and variable shadowing. It explains why similar-looking lines produce different constructor calls and notes a related mutex-locking hazard and an upcoming Clang warning.

## Source excerpt

What is the output of this small snippet that is based on real C++ code? #include <iostream> struct Foo { Foo() { std::cout << "standard" << std::endl; } Foo(const Foo&) { std::cout << "copy" << std::endl; } Foo(int) { std::cout << "int" << std::endl; } Foo(int, int) { std::cout << "int, int" << std::endl; } Foo(const Foo&, int) { std::cout << "Foo, int" << std::endl; } Foo(int, const Foo&) { std::cout << "int, Foo" << std::endl; } }; void f(Foo) {} struct Bar { int m_i; int m_j; Bar() { f(Foo(m_i, m_j)); f(Foo(m_i)); Foo(m_i, m_j); Foo(m_i); Foo(m_i, m_j); } }; int main() { Bar(); } The code compiles without warnings with clang++ 5.0.0 as well as g++ 7.2.0 using -Wall -Wextra. Solution The preliminaries are simple: We have a struct Foo with a few different constructors, each of which prints a text that represents its parameter types. We have a struct Bar with two members, m_i and m_j. The main function calls the standard constructor of Bar. The constructor of Bar is where the magic happens, so let's go through it line by line: f(Foo(m_i, m_j)) creates a temporary Foo object by calling the Foo constructor with m_i and m_j as parameters, so int, int is printed. The resulting Foo object is then passed to the function f. f(Foo(m_i)) works analogously, it calls the Foo constructor with m_i as parameter, so int is printed. The resulting Foo object is then passed to the function f. Foo(m_i, m_j) works the same as the first line, except it doesn't pass the resulting temporary Foo object to a function, so it is destroyed again immediately, int, int is printed again. So far so good, but now look closely. Foo(m_i) surprisingly behaves entirely differently from all the previous lines. It does not call the Foo constructor with m_i as the parameter. Instead it creates a Foo object of the name m_i, just like Foo m_i would. So standard is printed. Now the last line looks just like the third line, but it still does something different. Why? Because the name m_i is no longer referri