Curated interview practice questions with answers. These are practice scenarios, not a verified list of past interview questions.
About Adobe hiring for C++ roles
Adobe makes creative, document and marketing software including Photoshop, Acrobat, Premiere Pro, Adobe Express and Adobe Experience Cloud. Its Noida and Bengaluru centres are among its largest engineering sites globally. It hires in India for software engineers, quality engineers, data scientists and analysts working on product analytics, marketing data and AI features such as Firefly.
For C++ roles, this Adobe practice set focuses most on Object-Oriented Programming in C++ (7), Performance, Debugging and Build Tools (4), Multithreading and Concurrency (4), Pointers and Memory Management (3). It has 1 easy, 18 medium, 11 hard questions, so you can start easy and work up to the harder ones.
Company type
Product
Headquarters
San Jose, California, USA
Main India offices
Noida, Bengaluru, Gurugram
Adobe C++ interview process
Online assessment (aptitude + coding)
Technical round 1 (DSA)
Technical round 2 (DSA + CS fundamentals)
Hiring manager round
HR round
Typical pattern based on public candidate experiences. Rounds vary by role, team and year.
Solved for AdobeStart 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.
✓ 3 questions free • Unlock the rest in seconds
01
Should a Car class inherit from Engine or contain an Engine? Explain your choice.
A car is not an engine, it has an engine, so composition is correct: class Car holds an Engine member or a unique_ptr<Engine>. Inheritance models an is-a relationship and exposes the base interface, which would let callers treat a Car as an Engine. Composition also allows swapping engine types at run time through an interface such as PetrolEngine or ElectricMotor and keeps coupling low.
02
Show the compiler commands to build with strict warnings and sanitizers enabled.
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.
04
What is the difference between a shallow copy and a deep copy?
A shallow copy copies pointer members, so two objects share one heap buffer; destroying one leaves the other dangling and causes a double free. A deep copy allocates new memory and copies the contents. The compiler-generated copy constructor copies member by member, so a class owning a raw pointer needs a custom copy constructor and copy assignment, or better, should hold a std::vector or unique_ptr instead.
05
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.
06
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.
07
What does C++20 std::jthread add over std::thread?
std::jthread joins automatically in its destructor, so forgetting join no longer calls std::terminate. It also supports cooperative cancellation: the thread function can take a std::stop_token, check stop_requested() in its loop, and the owner calls request_stop(), which the destructor also does before joining. std::stop_callback lets you register cleanup actions. This makes long-running worker threads safer to write.
08
What is undefined behaviour in C++? Give examples.
Undefined behaviour means the standard places no requirement on the result, so the program may crash, print garbage or appear to work. Examples are signed integer overflow, reading an uninitialised variable, out-of-bounds array access, dereferencing a null or dangling pointer and data races. Optimisers assume UB never happens and remove checks based on that, so such bugs often appear only in optimised release builds.
09
You inherit a 3000-line class that handles parsing, validation, database and logging. How would you refactor it?
It breaks the single responsibility principle. First I add characterisation tests around current behaviour. Then I extract cohesive pieces into separate classes such as Parser, Validator and Repository, injected through interfaces so they can be mocked. I move step by step, keeping the old public API as a facade, and merge small refactors frequently instead of one big rewrite, so risk stays low and reviews stay easy.
10
Using a custom struct as the key of an unordered_map gives a compile error. Why, and how do you fix it?
unordered_map needs a hash function and equality comparison for the key type, and std::hash is not defined for user structs. Fix it by defining operator== (or defaulting it in C++20) and providing a hash functor that combines member hashes, passed as the third template argument, or by specialising std::hash for the type. std::map instead needs operator< or a comparator.
11
How do you handle a tight deadline when the C++ code you need to change is complex?
Situation: a client needed a protocol change in two days in code I had not touched. Task: deliver safely. Action: I read the tests first, wrote two new tests for the required behaviour, made the smallest change that passed them, and flagged a risky area to my lead early instead of at the end. I logged a refactoring ticket for later. Result: we shipped on time with no regressions and cleaned up the module the next sprint.
CPUs access data fastest at addresses that are multiples of its size, so the compiler aligns members and inserts padding bytes. A struct of char, int, char is usually 12 bytes, while ordering it as int, char, char gives 8. alignof reports alignment and alignas raises it, for example to 64 bytes to keep data used by different threads on separate cache lines. Packed structs save space but may be slower.
Most compilers give each polymorphic class a vtable, a static table of function pointers for its virtual functions. Every object stores a hidden vptr pointing to its class's vtable. A call through a base pointer loads the vptr, looks up the slot and jumps to the right override. The cost is one pointer per object, an indirect call and usually no inlining, which matters only in very hot loops.
14
Tell me about a code review where you pointed out an important issue in a colleague's code.
Situation: a colleague's change stored pointers to vector elements in a map and then appended to the vector. Task: flag the risk without discouraging them. Action: I commented with a short example showing reallocation invalidating the pointers, suggested storing indices or using std::deque, and offered to pair on the fix. Result: the bug was fixed before release, and we added a checklist item on iterator invalidation for reviews.
15
Write a GoogleTest unit test for a function, including an edge case.
I would measure with Clang -ftime-trace or build tooling to find the slowest files and headers. Then reduce header dependencies using forward declarations and the pimpl idiom, use Ninja for parallel builds, enable ccache or sccache, add precompiled headers for stable heavy headers, and split huge translation units. Unity builds and distributed compilation also help, and CI can cache build outputs.
17
When would you use std::set versus std::priority_queue?
priority_queue is a binary heap that gives O(1) access to the largest element and O(log n) push and pop, but you cannot search or erase arbitrary elements. std::set keeps all elements sorted with O(log n) insert, erase and find, and gives both minimum and maximum. Use priority_queue for schedulers and Dijkstra, and set or multiset when you must update or remove arbitrary items.
18
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.
19
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.
20
What is std::atomic and what do memory orderings mean?
std::atomic<T> makes reads, writes and read-modify-write operations such as fetch_add indivisible and race-free without a mutex. Memory order controls how other memory operations are ordered around it. seq_cst, the default, gives one global order and is easiest to reason about. acquire and release pair up to publish data from one thread to another. relaxed only guarantees atomicity, suitable for simple counters. Weaker orders are faster but harder to get right.
21
Write a deadlock-free money transfer between two bank accounts.
Templates give static polymorphism: resolved at compile time, inlinable and fast, but types must be known at compile time and code size grows. Virtual functions give dynamic polymorphism: one compiled body, types can be chosen at run time, plugins are possible, at the cost of an indirect call. I use templates for performance-critical generic algorithms and virtual interfaces for runtime-configurable components.
25
Write a move constructor and move assignment operator for a class that owns a buffer.
A std::thread object that is still joinable was destroyed, often because the function returned early or threw before reaching join. The std::thread destructor calls std::terminate in that case. Fix it by making sure every thread is joined on all paths, using an RAII guard, or switching to std::jthread, which joins automatically. Be careful with detach, since detached threads may access destroyed data.
27
Your program gives correct output in a debug build but wrong output in a release build. How do you investigate?
This usually means undefined behaviour or an uninitialised variable that the optimiser exploits. I would compile with -Wall -Wextra and fix every warning, then run tests with -fsanitize=address,undefined to catch out-of-bounds access, overflow and use-after-free. ThreadSanitizer checks for data races. Building with -O2 -g lets me debug the optimised code, and bisecting functions or adding assertions narrows down the faulty spot.
28
Design a class structure for UPI, card and net banking payments in a checkout system.
I would define an abstract PaymentMethod interface with virtual functions such as authorize, capture, refund and a virtual destructor. UpiPayment, CardPayment and NetBankingPayment implement it with their own validation. Checkout depends only on PaymentMethod, and a factory creates the right object from user choice. New methods such as wallets can be added without touching checkout code, which follows the open-closed principle.
29
A hot loop calls a virtual function millions of times and profiling shows the indirect call cost. What can you do?
Options include static polymorphism with CRTP or templates so calls can be inlined, marking classes or functions final so the compiler can devirtualise, and batching work by type so each loop handles one concrete class. Another option is replacing the hierarchy with std::variant and std::visit. I would confirm with a benchmark first, because often memory layout matters more than the virtual call itself.
30
What is the difference between full and partial template specialization?
Full specialization provides a separate implementation for one exact set of template arguments, such as template <> class Hash<std::string>. Partial specialization, allowed only for class and variable templates, covers a family of arguments, such as template <typename T> class Hash<T*> for all pointer types. Function templates cannot be partially specialised; overloading is used instead.
Tips to crack the Adobe C++ interview
Practise DSA and puzzles, which have commonly appeared in Adobe interviews alongside OOP and operating system questions.
Use Adobe Acrobat or Express and be ready to suggest a feature or test plan for one of its products.
For data roles, read about Adobe Analytics and Experience Platform, since many teams work on customer and marketing data.
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; Adobe interviewers usually ask follow-ups on your first answer.
Frequently asked questions
How many rounds are there in the Adobe C++ interview?
Candidates usually go through 5 stages: Online assessment (aptitude + coding); Technical round 1 (DSA); Technical round 2 (DSA + CS fundamentals); 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 Adobe C++ interview?
This practice set leans on Object-Oriented Programming in C++ (7), Performance, Debugging and Build Tools (4), Multithreading and Concurrency (4), Pointers and Memory Management (3). Revise those first, then practise explaining one or two of your own projects end to end, because most Adobe interviewers ask you to walk through real work.
Are these the exact questions asked at Adobe?
No. These are curated practice questions that match the skills and difficulty usually tested in product interviews like Adobe's. They are not a leaked or verified list of past questions.
Where does Adobe hire C++ professionals in India?
Adobe has large teams in Noida, Bengaluru, Gurugram. Openings and locations change often, so check the Adobe careers page and filter by city and experience.