Skip to Content
Course content
Click on the "Edit" button in the top corner of the screen to edit your slide content.

In the previous lessons, we've spent a lot of time breaking logic into functions. That's generally the right move—it makes code readable and reusable. But there's a hidden cost to every function call: the "overhead." The CPU has to push arguments onto the stack, jump to a different memory address, execute the code, and then jump back. In 99% of your code, this cost is invisible. But if you're writing a physics engine or a high-frequency trading app where a function is called ten million times a second, that overhead starts to eat your performance.

The overhead of a simple distance check

Let's look at a concrete example. Imagine we're building a simple 2D game. We need to check the distance between two points constantly to see if a player is within range of an enemy. I'll start by defining a basic Point struct and a function to calculate the squared distance between two of them. (I'm using squared distance because calculating a square root is computationally expensive and usually unnecessary for simple comparisons.)

struct Point {
    float x, y;
};

float getDistanceSq(Point p1, Point p2) {
    float dx = p1.x - p2.x;
    float dy = p1.y - p2.y;
    return (dx * dx) + (dy * dy);
}

Now, getDistanceSq is tiny. It's basically two subtractions and two multiplications. The time it takes the CPU to actually jump to this function is almost as long as the time it takes to do the math inside it. This is where inline comes in. By marking a function inline, you're suggesting to the compiler: "Don't make a function call here. Just copy and paste the logic directly into the spot where the function is called."

The trap of the separate compilation unit

Here is where I usually trip up when I'm rushing a project. I'll write my inline function in a .cpp file, thinking I'm keeping my headers clean. Let's see how that looks:

// MathUtils.cpp
#include "MathUtils.h"

inline float getDistanceSq(Point p1, Point p2) {
    float dx = p1.x - p2.x;
    float dy = p1.y - p2.y;
    return (dx * dx) + (dy * dy);
}

I'll compile this, and then I'll try to use getDistanceSq in my main.cpp. I'll get a linker error. Why? Because the compiler needs to see the actual body of the function to "inline" it into the calling code. If the definition is tucked away in a separate .cpp file, the compiler can't see the logic while it's processing main.cpp, so it tries to do a traditional function call. But because I marked it inline, the compiler might not have generated a traditional external symbol for it. The linker then looks for the function and finds... nothing.

Getting the visibility right

To fix this, inline functions almost always need to live in the header file. This allows every file that includes the header to see the implementation and perform the substitution. I'll move the logic into MathUtils.h:

// MathUtils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

struct Point {
    float x, y;
};

inline float getDistanceSq(Point p1, Point p2) {
    float dx = p1.x - p2.x;
    float dy = p1.y - p2.y;
    return (dx * dx) + (dy * dy);
}

#endif

One quick side note: you'll notice that if you define a function inside a class definition, C++ treats it as inline by default. You don't need to explicitly type the keyword. I used a standalone function here just to make the mechanics of the inline keyword clear.

Keep in mind that inline is a request, not a command. Modern compilers are incredibly smart; if your function is too complex (like containing a massive loop or recursion), the compiler will ignore your inline request and treat it as a regular function. Conversely, if the compiler sees a tiny function that isn't marked inline, it might decide to inline it anyway. Use it as a hint for your most critical, smallest functions, but don't rely on it as a magic "make fast" button.




📋 Practical Task

Build a High-Performance Bounding Box Collider

You are tasked with creating a simple collision detection utility for a 2D game. To ensure the physics loop runs as fast as possible, you need to implement an inline check to see if a point is inside a rectangular bounding box.

Requirements:

  • Create a Rect struct with float left, top, right, bottom.
  • Implement an inline function called isPointInRect that takes a Point (from the previous lesson) and a Rect.
  • The function should return true if the point's x-coordinate is between left and right, and its y-coordinate is between top and bottom.
  • Ensure the function is defined in a way that it is visible to any file including your header (avoid the linker error mentioned in the lesson).
  • In your main function, create a Rect and a Point, then call your function and print the result to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.