Fundamentals 14 min read

Ten Modern C++ Features to Boost Readability, Maintainability, and Performance

This article introduces ten widely used modern C++ features—including range‑based for loops with initializers, structured bindings, inline variables, std::optional, std::variant, std::visit, constexpr if, default/delete functions, [[nodiscard]] and std::string_view—explaining their benefits and providing concise code examples.

IT Services Circle
IT Services Circle
IT Services Circle
Ten Modern C++ Features to Boost Readability, Maintainability, and Performance

C++ has evolved since its first release in 1983, and with the arrival of C++11, C++14, C++17, C++20 and later standards, many modern features have been added that make the language more powerful and expressive. Today C++ is not only a strong system‑level language but also an efficient, flexible tool used in a wide range of applications.

About ten years ago the author started using Modern C++ in a project with GCC 4.9.2 (C++11 support), later upgrading to GCC 11.2 and now GCC 14.2 to take advantage of newer language features.

This article briefly introduces ten commonly used modern C++ features that can improve code readability, maintainability, and execution efficiency.

Note: The article provides a simple overview and does not dive deeply into each feature’s usage or implementation details.

It is hoped that readers will gain a better understanding of Modern C++ through this guide.

Range‑based for loop with initializer

C++20 extends the range‑based for loop with an initializer, allowing a variable to be declared in the loop header, which simplifies code and limits the variable’s scope.

std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto size = numbers.size(); auto&& num : vec) {
    std::cout << num << " " << size;
}

This feature is especially useful when a variable is needed only inside the loop, preventing accidental use elsewhere.

Structured bindings

Introduced in C++17, structured bindings allow tuples, pairs, and other multi‑element objects to be unpacked into named variables, greatly improving code readability.

#include <map>
#include <string>
#include <iostream>

int main() {
    std::map<std::string, int> ages = {{"A", 30}, {"B", 25}};
    for (auto&& [name, age] : ages) {
        std::cout << name << " is " << age << " years old." << std::endl;
    }
    return 0;
}

Structured bindings are handy when handling functions that return multiple values or when iterating over key‑value containers.

inline variable

C++17 introduced inline variables, whose semantics are similar to inline functions but apply to variables.

The most common use is initializing static class members:

class Test {
private:
    inline static int value_ = 0; // equivalent to defining int Test::value_ = 0; outside the class
};

Like inline functions, an inline variable can be defined in multiple translation units, with the linker keeping a single definition. All definitions must be identical.

Inline variables also allow defining global variables in header files without violating the One Definition Rule (ODR).

std::optional

C++17 added std::optional, offering a safer and more expressive way to handle optional values, serving as a better alternative to sentinel values or raw pointers.

struct Result {
  char c;
  uint32_t pos;
};

std::optional<Result> GetFirstUpper(const std::string &str) {
  std::optional<Result> res;
  for (int i = 0; i < str.size(); ++i) {
    if (std::isupper(str[i])) {
      res.c = str[i];
      res.pos = i;
      return res;
    }
  }
  return std::nullopt;
}
std::optional

is particularly useful for functions that may or may not return a value, eliminating the need for error codes or exceptions in many cases.

std::variant

std::variant

, introduced in C++17, is a type‑safe union that can hold one of several different types at a time, providing compile‑time type checking.

#include <variant>
#include <string>
#include <iostream>

int main() {
    std::variant<int, float, std::string> data;
    data = 10;
    std::cout << std::get<int>(data) << std::endl;
    data = "Hello";
    std::cout << std::get<std::string>(data) << std::endl;
    return 0;
}
std::variant

is useful when handling multiple possible types, such as parsing different data formats or implementing state machines.

std::visit

std::visit

(C++17) is a function template that visits the value stored in a std::variant, allowing type‑specific operations without manual type checks.

#include <variant>
#include <string>
#include <iostream>

struct Visitor {
    void operator()(int i)   { std::cout << "Integer: " << i << std::endl; }
    void operator()(float f) { std::cout << "Float: " << f << std::endl; }
    void operator()(const std::string &s) { std::cout << "String: " << s << std::endl; }
};

int main() {
    std::variant<int, float, std::string> data = 3.14f;
    std::visit(Visitor{}, data);
    return 0;
}
std::visit

enables clean, type‑safe handling of the actual type stored in a variant.

constexpr if

constexpr if

, added in C++17, allows compile‑time conditional inclusion of code blocks, making template programming more flexible and avoiding unnecessary code generation.

#include <type_traits>
#include <iostream>

template <typename T>
void PrintType(const T& value) {
    if constexpr (std::is_integral_v<T>) {
        std::cout << "Integral type: " << value << std::endl;
    } else if constexpr (std::is_floating_point_v<T>) {
        std::cout << "Floating-point type: " << value << std::endl;
    } else {
        std::cout << "Other type" << std::endl;
    }
}

int main() {
    PrintType(42);
    PrintType(3.14);
    PrintType("Hello");
    return 0;
}
constexpr if

reduces the need for SFINAE tricks, resulting in clearer and more maintainable code.

default & delete

In C++11, defaulted and deleted functions allow explicit control over special member functions (constructors, copy/move, assignment, destructor), improving safety and intent.

#include <iostream>
class Obj {
public:
    Obj() = default;               // default constructor
    Obj(const Obj&) = default;    // default copy constructor
    Obj& operator=(const Obj&) = default; // default copy assignment
    ~Obj() = default;              // default destructor
};

int main() {
    Obj obj1;      // uses default constructor
    Obj obj2 = obj1; // uses default copy constructor
    obj1 = obj2;   // uses default copy assignment
    return 0;
}

[[nodiscard]] attribute

Introduced in C++17, the [[nodiscard]] attribute warns when the return value of a function is ignored, helping prevent accidental loss of important results.

#include <iostream>

[[nodiscard]] int GetArea(int width, int height) {
    return width * height;
}

int main() {
    GetArea(5, 10); // triggers warning because the result is ignored
    int area = GetArea(5, 10); // correct usage
    std::cout << "Area: " << area << std::endl;
    return 0;
}

std::string_view

std::string_view

(C++17) provides a non‑owning view of a string, avoiding copies and unnecessary memory allocations.

#include <iostream>
#include <string_view>

void Print(std::string_view str) {
    std::cout << "String: " << str << std::endl;
}

int main() {
    std::string_view view = "Hello, World!";
    Print(view);
    return 0;
}

Conclusion

The ten features described above are widely used in many projects; of course, there are also lambda expressions, auto, and others not covered here. It is hoped that this article helps you adopt Modern C++ more effectively.

<p style="text-align:center"><img src="https://mmbiz.qpic.cn/mmbiz_gif/Ljib4So7yuWgtu32lo8txTia7urcjBx8VnHePPpZ8xSbEdsS8Hou17v7epnoibWWkIuHjVEd19ZWn0SibXEfvPPIxA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp" style="width:212px !important"/></p><section><p>1、<a href="https://mp.weixin.qq.com/s?__biz=MzUyMTY4MTk2OA==&mid=2247673944&idx=3&sn=678932539c84ee83aa7f8c54b3a10011&scene=21#wechat_redirect" target="_blank">2025年TypeScript已经不够用了,搭配这个每周下载2000万次的神器使用,完美!</a></p><p>2、<a href="https://mp.weixin.qq.com/s?__biz=MzUyMTY4MTk2OA==&mid=2247673900&idx=3&sn=3cc2e8bc54c5a74c76fb0a5f2c089838&scene=21#wechat_redirect" target="_blank">京东一面:什么是消息轨迹?broker节点配的。</a></p><p>3、<a href="https://mp.weixin.qq.com/s?__biz=MzUyMTY4MTk2OA==&mid=2247673899&idx=3&sn=9b5174491f751d5a7811bdaa5a06c14b&scene=21#wechat_redirect" target="_blank">阿里二面:使用消息队列怎样防止消息重复?</a></p><p>4、<a href="https://mp.weixin.qq.com/s?__biz=MzUyMTY4MTk2OA==&mid=2247673890&idx=3&sn=ddb96584de07f93eeb9b623e8ab81bf5&scene=21#wechat_redirect" target="_blank">瞧瞧别人家的判空,那叫一个优雅!</a></p><p>5、<a href="https://mp.weixin.qq.com/s?__biz=MzUyMTY4MTk2OA==&mid=2247673763&idx=3&sn=ea10d477c928e3e1a5a6c17b00fb8f19&scene=21#wechat_redirect" target="_blank">Go 下一步计划,新标准库 sync/v2!</a></p><p style="text-align:center"><img src="https://mmbiz.qpic.cn/mmbiz_gif/Ljib4So7yuWhV286BqNMwDMKWbMic75en4IFH3HQqFtoiau9PLcbwvKEBlkUJqs3k2WCCm7Vbv39dcUDNN1dPy7hA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1&tp=webp" style="width:20px !important"/></p></section>
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

programmingCode OptimizationC++language featuresC++20modern C++C++17
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.