简体   繁体   中英

How c++ compilers extend template<> code and how does it affect speed of same?

I am little lost with templates, and how compiler processes them.

Needed some generic wrapper for std::vector<< SomeType * >>* lpVars; that is capable of performing delete on all items contained inside that vector when I delete lpVars. Something similar to the C#'s List<> (generic list class). So I went for templates and wrote something like this:

template<class T>
class ListPtr
{
public:
  std::vector<T*> items;
  ListPtr()
  { }
  ~ListPtr()
  {
    size_t count = items.size();
    for(size_t i=0; i<count; i++)
    {
      T* item = items[i];
      delete item;
    }
    items.clear();
  }
  inline const int count() const
  {
    return (int)items.size();
  }
  inline T* operator[](size_t index) const
  {
    return items[index];
  }
  inline void Add(T* item)
  {
    items.push_back(item);
  }
};

later on I declared global type lists like:

class SomeType1List : public ListPtr<SomeType1> {};
class SomeType2List : public ListPtr<SomeType2> {};
...
class SomeTypeNList : public ListPtr<SomeTypeN> {};

Here is the first part of my interest on subject:

(1) Are this classes SomeType1List, SomeType1List, ..., SomeTypeNList fully preprocessed to templates code with replaced T template type for each declaration (SomeType1, SomeType2, ..., SomeTypeN) like there is no template (are fully declared classes), or compiler performs some other magic here?

(2) And if compiler performs some other magic, how should I define this types that compiler would compile them as they are fully declared classes?


To explain usage of above code more precise:

this list instances are initialized, and returned from functions like following one:

SomeType1List* GetItems()
{
  SomeType1List* items = new SomeType1List();
  for(int i=0; i<1000; i++)
  {
    SomeType1* item = new SomeType1();
    // feed item with some data
    items->Add(item);
  }
  return items;
}

and used in other parts of code like this:

SomeType1List* items = GetItems();
int count = items->count();
for(int i=0; i<count; i++)
{
  SomeType1* item = items[i];
  // do something with item;
}
delete items; // all memory occupied by items released after this line

Second part of my interest on subject:

(3) Could this be written differently using only standard classes (no boost or similar sdks)? goal is speed but to keep code clean and easy to read. So this question would be is there any better way to do all of this?

  1. Yes

  2. No magic here

  3. You can use std::vector<std::unique_ptr<T>> (C++11) or std::vector<std::auto_ptr<T>> (kind of deprecated)

Example:

#include <iostream>
#include <memory>
#include <vector>

class T
{
private:
    unsigned int _i;

public: 
    void print() const
    {
        std::cout << "Print: " << _i << std::endl;
    }

    T(unsigned int i)
    {
        _i = i;

        std::cout << "Constructor! " << _i << std::endl;
    }

    ~T()
    {
        std::cout << "Destructor! " << _i << std::endl;
    }
};

std::vector<std::unique_ptr<T>>* createStuff()
{
    auto output = new std::vector<std::unique_ptr<T>>;

    for(unsigned int i = 0; i < 5; i++)
    {
        output->emplace_back(new T(i));
    }

    return output;
}

int main()
{
    std::cout << "Begin!" << std::endl;

    auto stuff = createStuff();

    for(std::unique_ptr<T> const& thing : *stuff)
    {
        thing->print();
    }

    delete stuff;

    std::cout << "End!" << std::endl;

    return 0;
}

Output:

Begin!
Constructor! 0
Constructor! 1
Constructor! 2
Constructor! 3
Constructor! 4
Print: 0
Print: 1
Print: 2
Print: 3
Print: 4
Destructor! 0
Destructor! 1
Destructor! 2
Destructor! 3
Destructor! 4
End!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM