Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Morgan Stanley hiring for C++ roles
Morgan Stanley is a global financial services firm focused on investment banking, sales and trading, wealth management and investment management. Its India offices in Mumbai and Bengaluru are large technology and analytics hubs. It hires for software engineers, QA engineers, data engineers, quantitative analysts and risk or finance analysts.
For C++ roles, this Morgan Stanley practice set focuses most on Object-Oriented Programming in C++ (6), Multithreading and Concurrency (5), Standard Template Library (STL) (4), Performance, Debugging and Build Tools (4). It has 2 easy, 23 medium, 5 hard questions, so you can start easy and work up to the harder ones.
Company type
Banking & finance
Headquarters
New York, USA
Main India offices
Mumbai, Bengaluru
Morgan Stanley C++ interview process
Online assessment (coding + aptitude)
Technical round 1
Technical round 2
Hiring manager round
HR round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for Morgan StanleyStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
A condition variable lets a thread sleep until another thread signals that some state changed. The waiter holds a unique_lock and calls cv.wait(lock, predicate), which releases the mutex while sleeping and reacquires it on wake. The notifier changes the state under the mutex and calls notify_one or notify_all. Threads can wake without notification, called spurious wakeups, so always wait with a predicate that rechecks the condition.
GoogleTest with GoogleMock is the most widely used; it provides TEST and TEST_F macros, assertions such as EXPECT_EQ and ASSERT_TRUE, fixtures and mocking. Catch2 and doctest are lightweight, header-friendly alternatives with natural syntax. Tests are usually registered with CTest in CMake and run in CI on every merge. Good tests are fast, independent and cover edge cases like empty input and overflow.
I would use a bounded thread-safe queue built with a mutex and two condition variables, one for not empty and one for not full, so a fast reader cannot exhaust memory. The reader pushes lines and workers pop and parse them. For shutdown, the reader pushes a sentinel per worker or sets a closed flag and notifies all. Batching lines per push reduces locking overhead, and results go to a second queue.
08
Write a minimal modern CMakeLists.txt for an app with a library and tests.
Ranges let algorithms take whole containers, as in std::ranges::sort(v), instead of begin and end pairs. Views such as filter, transform, take and reverse are lazy and compose with the pipe operator, for example v | std::views::filter(isEven) | std::views::transform(square). Nothing is computed until you iterate. Ranges also use concepts, so errors are clearer, and projections let you sort by a member easily.
Resource Acquisition Is Initialization ties a resource's lifetime to an object's lifetime. The constructor acquires the resource, such as memory, a file, a socket or a mutex, and the destructor releases it. Because destructors run automatically when a scope ends, even when an exception is thrown, resources are never leaked. std::unique_ptr, std::lock_guard and std::fstream are standard RAII types.
11
You need a container that holds ints, strings and doubles together. Which approach would you choose?
If the set of types is fixed and known, std::vector<std::variant<int, std::string, double>> is type-safe and needs no heap per element; std::visit handles each type. If types are open-ended, std::any works but needs any_cast and loses compile-time checks. If the items share behaviour, a base class interface with unique_ptr is cleanest. I usually prefer variant for closed sets.
12
What are type traits and how does if constexpr use them?
Type traits in <type_traits> answer questions about types at compile time, such as std::is_integral_v<T>, std::is_pointer_v<T> or std::is_same_v<T, U>, and transform types, such as std::remove_reference_t. if constexpr picks a branch at compile time and discards the other, so code like if constexpr (std::is_integral_v<T>) can call integer-only operations safely inside a generic function.
13
Explain the rule of three, rule of five and rule of zero.
Rule of three: if a class needs a custom destructor, copy constructor or copy assignment, it usually needs all three because it manages a resource. Rule of five adds the move constructor and move assignment from C++11. Rule of zero says the best design avoids writing any of them by holding resources in members such as std::vector, std::string and unique_ptr, which already manage themselves.
14
What is the difference between push_back and emplace_back?
push_back takes an existing object, copying or moving it into the container. emplace_back forwards constructor arguments and builds the element directly in place, which can avoid a temporary. For example v.emplace_back(name, age) constructs a Person inside the vector. The gain is small when you already have an object, and emplace_back can call explicit constructors unexpectedly, so use it deliberately.
15
A C++ server crashes with a segmentation fault in production. How do you debug it?
Make sure core dumps are enabled with ulimit -c unlimited or systemd-coredump, and keep debug symbols for release builds. Load the core with gdb binary core, run bt to see the stack trace, then inspect frames and variables. If the stack looks corrupted, reproduce in staging with AddressSanitizer. I would also check logs around the crash time and recent deployments, then add a regression test with the fix.
16
You call a virtual function from a base class constructor but the derived override never runs. Why?
During base construction the derived part does not exist yet, so the object's dynamic type is the base and the vptr points to the base vtable. Virtual calls in constructors and destructors therefore go to the version of the class currently being built. Calling a pure virtual this way is undefined. Fix it with a two-phase init method called after construction or a factory function that constructs and then configures.
17
What are AddressSanitizer, UndefinedBehaviorSanitizer and ThreadSanitizer?
They are compiler instrumentation tools in GCC and Clang. ASan, -fsanitize=address, detects out-of-bounds access, use-after-free, double free and leaks with about 2x slowdown. UBSan, -fsanitize=undefined, catches signed overflow, invalid shifts and null dereferences. TSan, -fsanitize=thread, detects data races but cannot be combined with ASan. Running tests under sanitizers in CI catches bugs long before production.
18
Tell me about a time you designed the class structure for a module and how you handled review feedback.
Situation: I had to build a report export module supporting PDF, CSV and Excel. Task: design it so new formats were easy to add. Action: I proposed an abstract Exporter interface and a factory, shared a short design note and asked seniors to review before coding. They pointed out duplicated formatting logic, so I extracted a Formatter helper. Result: a fourth format was later added in one day with no changes to existing classes.
19
Write a custom hash so a struct can be used as a key in std::unordered_map.
Combine a doubly linked list with a hash map. std::list stores key-value pairs in usage order, with the most recent at the front. std::unordered_map maps each key to its list iterator. On get, splice the node to the front in O(1). On put, update or insert at the front and, if over capacity, remove the back node and its map entry. list iterators stay valid after splice, which makes this work.
21
Tell me about a time you wrote generic, reusable code that saved effort for your team.
Situation: three services each had their own copy of retry logic for network calls. Task: remove duplication without slowing them down. Action: I wrote a small header-only template, retry with a callable and a policy for attempts and backoff, added unit tests and documented examples. Result: all three services adopted it, around 600 lines of duplicate code were deleted and a bug fix now happens in one place.
A deadlock happens when threads wait forever for each other's locks, for example thread A holds m1 and waits for m2 while thread B holds m2 and waits for m1. It needs mutual exclusion, hold and wait, no preemption and circular wait. Prevent it by always locking in a fixed global order, locking several mutexes together with std::scoped_lock, keeping critical sections small and never calling unknown code while holding a lock.
An lvalue has identity and a persistent address, such as a named variable x. An rvalue is a temporary without lasting identity, such as 5 or the result of a + b. C++11 splits these further into lvalue, xvalue and prvalue. The distinction matters because rvalue references, written T&&, bind to temporaries and enable move semantics, letting the program steal resources instead of making expensive copies.
24
A function returns a reference to a local variable and the code sometimes works. Explain what is happening.
The local is destroyed when the function returns, so the reference dangles and using it is undefined behaviour. It may seem to work because the old bytes remain on the stack until another call overwrites them. Compilers warn with -Wreturn-local-addr or -Wreturn-stack-address. The fix is to return by value; copy elision and move semantics make returning objects cheap.
25
Many threads read a shared configuration object constantly, but it changes only once an hour. How do you synchronise it efficiently?
A plain mutex would serialise all readers. Option one is std::shared_mutex: readers take shared_lock and run in parallel, the updater takes unique_lock. Option two, often faster, is to keep the config in a std::shared_ptr<const Config> and swap in a new immutable object atomically with std::atomic<std::shared_ptr> in C++20; readers grab a copy of the pointer and never block the writer.
26
Explain the stages of compiling and running a C++ program.
There are four stages. The preprocessor expands #include directives and macros into a translation unit. The compiler turns each translation unit into assembly and then an object file. The linker combines object files and libraries and resolves symbols into an executable. At run time the loader maps it into memory. A missing function body therefore shows up as a linker error, not a compiler error.
27
Use a C++20 ranges pipeline to get squares of the first three even numbers.
#include <iostream>
#include <ranges>
#include <vector>
int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
auto result = v
| std::views::filter([](int x) { return x % 2 == 0; })
| std::views::transform([](int x) { return x * x; })
| std::views::take(3);
for (int x : result) std::cout << x << ' '; // 4 16 36
}
// Views are lazy: elements are processed only while iterating.
28
Overload operator+ and operator<< for a Complex number class.
Slicing happens when a derived object is copied into a base object by value. Only the base part is copied, the derived data is lost and virtual calls use the base version. Example: void draw(Shape s) called with a Circle loses Circle's radius and behaviour. Avoid it by passing polymorphic objects by reference or pointer, and consider deleting copy operations in polymorphic base classes.
30
What does the static keyword mean in different contexts?
Inside a function, a static local variable is initialised once and keeps its value between calls. At namespace scope, static gives internal linkage, so the name is visible only in that translation unit. Inside a class, a static data member belongs to the class rather than each object, and a static member function has no this pointer. Since C++17 inline static members can be defined directly in the header.
Tips to crack the Morgan Stanley C++ interview
Revise core Java, OOP, multithreading and SQL, which are often expected for Morgan Stanley technology roles.
Learn basics of wealth management and trading, such as order types, portfolios and market risk.
Prepare examples showing attention to detail and controls, which matter in a regulated financial environment.
Keep a one-minute story ready for every project on your CV: problem, your part, tools, result.
Practise the hard questions on this page aloud; Morgan Stanley interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Morgan Stanley C++ interview?
Candidates usually go through 5 stages: Online assessment (coding + aptitude); Technical round 1; Technical round 2; Hiring manager round; HR round. The exact rounds change with the role, team, location and your experience, so confirm the process with the recruiter.
Which topics should I prepare for the Morgan Stanley C++ interview?
This practice set leans on Object-Oriented Programming in C++ (6), Multithreading and Concurrency (5), Standard Template Library (STL) (4), Performance, Debugging and Build Tools (4). Revise those first, then practise explaining one or two of your own projects end to end, because most Morgan Stanley interviewers ask you to walk through real work.
Are these the exact questions asked at Morgan Stanley?
No. These are curated practice questions that match the skills and difficulty usually tested in banking & finance interviews like Morgan Stanley's. They are not a leaked or verified list of past questions.
Where does Morgan Stanley hire C++ professionals in India?
Morgan Stanley has large teams in Mumbai, Bengaluru. Openings and locations change often, so check the Morgan Stanley careers page and filter by city and experience.