You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ Array模板类正确创建方法求教(附代码)

Fixing Your C++ Array Template Class

Hey there! Let's walk through fixing your C++ Array template class—since this is for learning, I’ll break down the issues in your code and show you a more robust, idiomatic implementation step by step.

First, let's recap the code you shared (I’ll clean up the formatting a bit):

// Developed by Trofimov Yaroslav on 30.03.2018
#ifndef _ARRAY_H_TROFIMOV_
#define _ARRAY_H_TROFIMOV_
#include <string>

template<const size_t n, typename T>
class Array {
    static unsigned __freeId, __quantity;
    unsigned _id;
    T** _array;
    const size_t _n;
public:
    typedef const bool (* const BooleanResultDelegate)(const T&...);
    // Your code cuts off here, but we can work with what's present
};

Key Issues in Your Current Code

Let's go through the main problems that are likely causing you trouble:

  1. Static Member Initialization
    Template class static members (__freeId and __quantity) need explicit initialization outside the class, and each template instantiation gets its own copy of these members. Your code doesn’t include this step, which will cause linker errors.

  2. Unnecessary & Risky Memory Management
    Using T** _array is overcomplicating things for a fixed-size array. A raw double pointer requires manual allocation of both the pointer array and each element, which is error-prone (easy to leak memory or mess up deallocation). For a fixed-size template array, we can use safer alternatives like smart pointers or even a built-in array.

  3. Const Member Initialization
    The const size_t _n member must be initialized in the constructor’s initialization list—you can’t assign to it later. Also, since n is already a compile-time template parameter, storing it as a class member is redundant.

  4. Naming Conflicts
    Names starting with double underscores (__freeId, __quantity) are reserved for the C++ standard library. Using them can lead to undefined behavior, so it’s best to avoid them.

  5. Redundant const in Template Parameter
    Non-type template parameters like size_t n are already compile-time constants, so adding const to const size_t n is unnecessary.

Revised Implementation

Here’s a fixed, modern C++ version of your Array template class, with explanations of each change:

// Developed by Trofimov Yaroslav on 30.03.2018
#ifndef ARRAY_H_TROFIMOV_  // Removed leading underscores to avoid reserved names
#define ARRAY_H_TROFIMOV_
#include <iostream>
#include <memory>       // For smart pointers (safer memory management)
#include <stdexcept>    // For std::out_of_range

template<size_t n, typename T>  // Removed redundant const from template parameter
class Array {
    static unsigned freeId;      // Renamed to avoid double underscores
    static unsigned quantity;
    unsigned id;
    std::unique_ptr<T[]> array;  // Use smart pointer to manage array memory automatically

public:
    // Delegate type for boolean checks (completed your partial typedef)
    using BooleanResultDelegate = bool (*)(const T&);

    // Constructor: Initialize id, allocate array, track instance count
    Array() : id(freeId++), array(std::make_unique<T[]>(n)) {
        quantity++;
    }

    // Copy constructor: Perform deep copy to avoid shared memory issues
    Array(const Array& other) : id(freeId++), array(std::make_unique<T[]>(n)) {
        quantity++;
        // Copy each element from the original array
        for (size_t i = 0; i < n; ++i) {
            array[i] = other.array[i];
        }
    }

    // Destructor: Smart pointer auto-releases memory; just decrement instance count
    ~Array() {
        quantity--;
    }

    // Overload [] for mutable element access (with bounds checking)
    T& operator[](size_t index) {
        if (index >= n) {
            throw std::out_of_range("Array index out of bounds");
        }
        return array[index];
    }

    // Overload [] for const element access
    const T& operator[](size_t index) const {
        if (index >= n) {
            throw std::out_of_range("Array index out of bounds");
        }
        return array[index];
    }

    // Get compile-time array size (constexpr for compile-time evaluation)
    constexpr size_t size() const {
        return n;
    }

    // Get instance ID
    unsigned getId() const {
        return id;
    }

    // Get total number of active Array instances
    static unsigned getQuantity() {
        return quantity;
    }

    // Example: Use the delegate to check if any element matches a condition
    bool findIf(BooleanResultDelegate predicate) const {
        for (size_t i = 0; i < n; ++i) {
            if (predicate(array[i])) {
                return true;
            }
        }
        return false;
    }
};

// Initialize template static members (required for linker to find them)
template<size_t n, typename T>
unsigned Array<n, T>::freeId = 0;

template<size_t n, typename T>
unsigned Array<n, T>::quantity = 0;

#endif // ARRAY_H_TROFIMOV_

How to Use the Revised Class

Here’s a quick test program to demonstrate how the class works:

#include "Array.h"
#include <string>

// Example predicate function for findIf
bool isEven(int x) {
    return x % 2 == 0;
}

bool isLongerThanThree(const std::string& s) {
    return s.length() > 3;
}

int main() {
    // Create an array of 5 integers
    Array<5, int> intArr;
    intArr[0] = 1;
    intArr[1] = 2;
    intArr[2] = 3;
    intArr[3] = 4;

    std::cout << "intArr size: " << intArr.size() << "\n";
    std::cout << "intArr[2]: " << intArr[2] << "\n";
    std::cout << "Does intArr have an even number? " << std::boolalpha << intArr.findIf(isEven) << "\n";

    // Create an array of 3 strings
    Array<3, std::string> strArr;
    strArr[0] = "Hi";
    strArr[1] = "Hello";
    strArr[2] = "Hey";

    std::cout << "\nstrArr size: " << strArr.size() << "\n";
    std::cout << "Does strArr have a long string? " << strArr.findIf(isLongerThanThree) << "\n";

    // Check total active instances
    std::cout << "\nTotal Array instances: " << Array<5, int>::getQuantity() << " (int) + " << Array<3, std::string>::getQuantity() << " (string) = 2\n";

    return 0;
}

Key Takeaways for Learning

  • Template Static Members: Always initialize them outside the class using template syntax.
  • Smart Pointers: Prefer std::unique_ptr or std::shared_ptr over raw pointers to avoid memory leaks and simplify code.
  • Compile-Time Constants: Use template parameters for fixed sizes to let the compiler optimize your code.
  • Bounds Checking: Adding checks to operator[] prevents silent undefined behavior from out-of-bounds access.

内容的提问来源于stack exchange,提问作者ggghahaha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:28:40