如何有效地计算定义指针的数量?

时间:2011-09-12 12:55:51

标签: c++ algorithm

我有以下C ++代码:

Some_class * temp1 = findTemp1(...); // returns NULL or a valid pointer
Some_class * temp2 = findTemp2(...); // returns NULL or a valid pointer
Some_class * temp3 = findTemp3(...); // returns NULL or a valid pointer

现在我想计算其中有多少返回了有效指针(0,1,2或3)。

我能想到的唯一方法就是逐一测试它们:

int count = 0;
if (temp1)
   count++;
if (temp2)
   count++;
if (temp3)
   count++;

对于3个指针,它并不太糟糕,但它不能很好地扩展。假设我没有重新定义findTempN函数(可能在计数器中传递),是否有更有效的方法?


非常感谢您的快速回复!不,我不会改变代码,我只是想知道我的其他选择是什么。我也意识到如果我使用像这样的不同文字来定义3个指针,我就不能要求“可扩展”的东西。当然,我没有想到你回答的事情:)

7 个答案:

答案 0 :(得分:11)

好吧,因为这是C ++,我们可以为追求简洁而疯狂......例如:

int count = !!temp1 + !!temp2 + !!temp3;

更新:我可能欠伊万一个关于这里发生了什么的解释。

假设temp是任何类型的指针,!temp强制指针值的强制转换为bool(我们想这样做)并否定结果(这是副作用)我们不想要)。如果指针为空,则导致true,如果指针不为空,则导致false,这与我们想要的相反。所以我们在前面添加另一个!来再次否定结果。

这使我们添加了三个bool值,将它们强制转换为int并执行添加,然后我们得到了最终结果。

您可能会发现更容易理解完全等效的

int count = (bool)temp1 + (bool)temp2 + (bool)temp3;

我没有使用,因为键入!!(bool)短三个字符(注意:您可能认为这是一个很好的技巧,但在编写代码时它是非常糟糕的想法根据您输入的字符数来做出决定。

这个故事的寓意是,做这种事情可以被称为聪明或残暴,取决于你问的是谁 - 但在C ++中,传统上对暴行有很高的容忍度。

请注意如果指针在某种类型的集合中以开头,您可以使用std::count_if编写更好看的代码,例如:< / p>

bool isNotNull(void* ptr) {
    return ptr != 0;
}

std::vector<Some_class*> vec;
vec.push_back(temp1);
vec.push_back(temp2);
vec.push_back(temp3);

int count = std::count_if(vec.begin(), vec.end(), isNotNull);

<强> See it in action

或者,正如MSalters在评论中非常巧妙地建议的那样,你可以通过计算 0的指针并从所有指针的数量中减去它来丢失isNotNull函数 - 但为此,你需要以某种方式知道这个数字是什么(如果它们在vector中很容易):

int count = vec.size() - std::count(vec.begin(), vec.end(), 0);

<强> See it in action

答案 1 :(得分:0)

#define N 3
typedef Some_class *PointerGenerator(...);
PointerGenerator funcs[N];
func[0] = &findTemp1;
func[1] = &findTemp2;
func[2] = &findTemp3;

Some_class *ptrs[N];
for(size_t i = 0; i < N; ++i) ptrs[i] = func[i]();
for(size_t i = 0; i < N; ++i) { if(ptrs[i]) ++count; }

C ++ 0x variant:

int count = std::count_if(ptrs, ptrs + N, [](const Some_class *i) -> bool { return i != NULL; } );

答案 2 :(得分:0)

你拥有的代码很好,不要乱用它。

引入微妙是一个常见的新手错误,不要这样做。

也就是说,NULL是一个有效的指针值,你可以做到,例如count += !!temp1 + !!temp2 + !!temp3(但这可能是新手混淆,实际上并不这样做。)

干杯&amp;第h。,

答案 3 :(得分:0)

如果所有指针都是同一类型,请将指针放在表中, 或者,如果你不能这样做,请制作指向指针的表格。然后 使用std::countstd::count_if。类似的东西:

SomeClass** pointerTable[] =
{
    &temp1,
    &temp2,
    &temp3,
    //  ...
};

struct IndirectIsNoNull
{
    bool operator()( SomeClass** p ) const
    {
        return *p != NULL;
    }
};

//  ...
int validPointerCount = std::count_if( begin( pointerTable ),
                                       end( pointerTable ),
                                       IndirectIsNoNull() );

答案 4 :(得分:0)

介绍一个static计数器。

template<typename T>
struct ValidPointer
{
  static unsigned int count;
};
template<typename T>
unsigned int ValidPointer<T>::count = 0;

template<typename T>
static void isValid (const T* const p)
{
  if(p)
    ValidPointer<T*>::count++;
}

用法:

isValid(temp1);
isValid(temp2);
...

在任何时候,如果你想要检索,

unsigned int count = ValidPointer<Some_class*>::count;

此代码可根据您的要求进行改进。

答案 5 :(得分:0)

之后你需要指针吗? temp另有建议。在这种情况下,你可以消除这些:

int count = 0;
if (findTemp1())
   count++;
if (findTemp2())
   count++;
if (findTemp3())
   count++;

答案 6 :(得分:-1)

在班级中隐藏计数器:

class Some_class {};

typedef Some_class* (*FindFunction_t)();

Some_class* findTemp1() {return NULL;}
Some_class* findTemp2() {return new Some_class;}
Some_class* findTemp3() {return new Some_class;}

class Finder
{
public:
    Finder() : count_(0) {}

    Some_class* CallAndCount(FindFunction_t fn) {return Count(fn());}
    int GetCount() const {return count_;}

private:
    Some_class* Count(Some_class* p) {if(p) count_++; return p;}

    int count_;
};

int main()
{
    Finder f;
    Some_class* temp1 = f.CallAndCount(findTemp1);
    Some_class* temp2 = f.CallAndCount(findTemp2);
    Some_class* temp3 = f.CallAndCount(findTemp3);
    std::wcout << f.GetCount() << L"\n";
}

名称不是最好的,并且有内存泄漏,但你应该明白这个想法。 我认为这符合您的可伸缩性目标,但如果您的查找函数需要参数

,则需要添加模板函数