【问题标题】:How c++ compilers extend template<> code and how does it affect speed of same?c++ 编译器如何扩展模板<> 代码以及它如何影响相同的速度?
【发布时间】:2014-01-12 01:49:59
【问题描述】:

我对模板以及编译器如何处理它们有点迷茫。

需要一些通用的 std::vector 包装器>* lpVars;当我删除 lpVars 时,它能够对该向量中包含的所有项目执行删除。类似于 C# 的 List (通用列表类)。 所以我去找模板写了这样的东西:

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);
  }
};

后来我声明了全局类型列表,例如:

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

这是我对主题感兴趣的第一部分:

(1) 这些类 SomeType1List、SomeType1List、...、SomeTypeNList 是否已完全预处理为模板代码,每个声明(SomeType1、SomeType2、...、SomeTypeN)都替换为 T 模板类型,例如没有模板(完全声明的类),或者编译器在这里执行了一些其他的魔法?

(2) 如果编译器执行了其他一些魔法,我应该如何定义编译器将编译它们的这些类型,因为它们是完全声明的类?


更准确地解释上述代码的用法:

这个列表实例被初始化,并从如下函数返回:

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;
}

并在代码的其他部分使用如下:

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

我对主题的第二部分兴趣:

(3) 仅使用标准类(不使用 boost 或类似的 sdks)可以以不同的方式编写吗?目标是速度,但要保持代码简洁易读。所以这个问题是有没有更好的方法来做这一切?

【问题讨论】:

  • @Dietmar Kühl:谢谢,这是错字;)

标签: c++ list templates pointers


【解决方案1】:
  1. 这里没有魔法

  2. 您可以使用 std::vector&lt;std::unique_ptr&lt;T&gt;&gt; (C++11) 或 std::vector&lt;std::auto_ptr&lt;T&gt;&gt;(不推荐使用)

例子:

#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;
}

输出:

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!

【讨论】:

  • 你可能想要unique_ptr&lt;T&gt;,而不是unique_ptr&lt;T*&gt;。我不认为std::vector&lt;std::auto_ptr&lt;T&gt;&gt; 有用。
  • @aschepler 是的,我的错。固定。
  • 感谢课程;) 还了解到 push_back() 会导致奇怪的模板错误(花了 30 分钟才找到)。现在我还有其他问题如何将项目汇集起来,并防止它被 auto_delete 破坏?
  • @SoLaR 我不明白你所说的“汇集项目”是什么意思。无论如何,如果您喜欢我的回答,如果您接受它会很好。 :)
  • sry 错误的词,并再次 sry 你的答案击中靶心;)但回到我的问题:如何将项目移动到另一个向量或变量,不需要相同的 auto_unique 类型,并防止默认删除从它的原始向量调用?我昨晚尝试了几件事。但是当执行退出原始向量上下文时,内存总是被破坏。例如,如果我将使用纯指针,我将使用 poirent 并将原始向量 NULL 放入该向量所在的位置,并重写 ~ListPtr 以不删除 NULL - 并且可能用很少的移动内存来填充那个丢失的项目
猜你喜欢
  • 1970-01-01
  • 2011-07-08
  • 1970-01-01
  • 2020-09-25
  • 1970-01-01
  • 2010-10-02
  • 2017-02-01
  • 2012-05-23
  • 1970-01-01
相关资源
最近更新 更多