Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ std::对于每个,运算符()重载的对象不保持状态_C++_Visual Studio 2008_Std - Fatal编程技术网

C++ std::对于每个,运算符()重载的对象不保持状态

C++ std::对于每个,运算符()重载的对象不保持状态,c++,visual-studio-2008,std,C++,Visual Studio 2008,Std,在回答这个问题时,我想到了以下代码: #include <string> #include <iostream> #include <algorithm> #include <vector> class Sizes { public: void operator() ( std::vector<int> v ) { sizeVec.push_back( v.size() ); } std

在回答这个问题时,我想到了以下代码:

#include <string>
#include <iostream> 
#include <algorithm>
#include <vector>

class Sizes
{
public:
    void operator() ( std::vector<int> v ) { 
        sizeVec.push_back( v.size() );  
    }
    std::vector<int> sizeVec;
};

void outFunc (int i) {
    std::cout << " " << i;
}
int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<std::vector<int>> twodVec;

    std::vector<int> vec;
    vec.push_back( 6 );
    twodVec.push_back( vec );
    vec.push_back( 3 );
    twodVec.push_back( vec );
    vec.push_back( 8 );
    twodVec.push_back( vec );
    vec.push_back( 3 );
    twodVec.push_back( vec );

    Sizes sizes;
    std::for_each( twodVec.begin(), twodVec.end(), sizes );
    std::for_each( sizes.sizeVec.begin(), sizes.sizeVec.end(), outFunc );

    return 0;
}
调试时会显示正在调用的Sizes::operator,并且sizeVec的大小会随着每次调用的增加而增加。但是,当第二个std::foreach被调用时,sizeVec是空的。。。我已经创建了一个涉及将向量传递到大小的解决方案,但是有人知道发生了什么吗?

std::for_每个函数都通过值而不是引用获取函子,因此原始对象不受影响。您需要执行以下操作:

sizes = std::for_each( twodVec.begin(), twodVec.end(), sizes );

下面显示的代码片段引用自我编写本文时的代码

#include <string>
#include <iostream> 
#include <algorithm>
#include <vector>

class Sizes
{
public:
    void operator() ( std::vector<int> v ) { 
_tmain从来都不是有效的main形式

这段代码最多只能用微软的编译器编译

而且,即使是微软的编译器,它也没有任何用途,除了一种特殊情况,即针对Windows 9x,而不是针对一般的Windows 9x

为什么要写更多的代码以使代码非标准且不适合非Windows程序员使用

使用标准的main

大小可以在这里自由复制,实际上是通过值传递的

但是,std::for_会返回最终结果的副本

您可以将其重新分配给大小,即使当函子包含向量时这是一种效率很低的方法

这个最终返回0;对于标准main不需要,因为它只表示标准main的默认返回值


干杯&嗯。

我会做一些不同的事情:

// (1) struct rather than class for functor (as it contains no state).
struct Sizes
{
    // (2) Keep a reference to the vector
    std::vector<int>&    sizeVec;

    Sizes(std::vector<int>& sizeVec): sizeVec(sizeVec) {}

    // (3) The functor can now be const as the the state is external
    void operator() ( std::vector<int> const& v ) const
    {                              //  ^^^^^^  (4) Pass parameter by const reference
                                   //              This avoids an unnecessary copy.
        sizeVec.push_back( v.size() );  
    }
};

std::for_each( twodVec.begin(), twodVec.end(), Sizes(vec) );
                                         //    ^^^^^^^^^^  Call using temporary
                                         //                No need for a Size variable.
您的第二个for_each和outpunc可以替换为一些标准对象:

std::copy(sizes.sizeVec.begin(),
          sizes.sizeVec.end(),
          std::ostream_iterator<int>(std::cout, " ")
         );
第二个虽然更模糊的注释是,通过将状态保持在Sizes对象之外,可以更容易地转换为C++0x lambda,当它明年到来时:

std::for_each( twodVec.begin(), twodVec.end(), Sizes(vec) );

// becomes

std::for_each( twodVec.begin(),
               twodVec.end(), 
               [&vec] ( std::vector<int> const& v ) {  vec.push_back(v.size()); }
             );

但是,更好的方法是将状态保留在函数调用之外,因为几乎是?所有的算法都要求函子可以任意复制。@GMan:for_每个都是规则的例外。它被明确设计成这样使用。将状态保留在函数调用之外会使重入变得棘手。谢谢,奥利,我已经忘记了这一点。对于任何看到boost的人来说,都可以使用boost.Ref来进一步简化它。@GMan:是的,这很有意义。但我不得不问:为什么这么麻烦?从语义上讲,这实际上等同于在函子中包含状态。无论哪种方式,函子的可观察行为都会随着时间的推移而变化,在容器上调用它的顺序也很重要。我会将向量放在Size类之外,并将其作为引用传递进来。这有两个额外的好处。1当函子传递给每个函数时,不复制向量。2它使得对for_的调用更加直观,因为操作员现在是const,而您不需要;I don’我不需要一个单独的变量,只是一个临时变量。我觉得这其中的大部分应该写在注释中,因为它模糊了你对问题本身的答案。@Alf:我在VS 2008中写过这篇文章,它会自动创建_tmain和返回0行,我为什么要更改它?关于通过引用传递向量,我想知道在调用for_时如何使用临时对象vec。OP的目的是获得一个对象,一个保持twodVec大小的向量。由于vec是临时性的,在调用for_each之后,该信息将丢失,不是吗?@gatitor048:根据定义,命名对象不能是临时对象。我所做的是将向量移出Sizes类,并将其作为命名变量vec放在调用类的范围内。原因是,for_的第三个参数是通过值传递的,这导致在循环的每次迭代中生成并可能生成第三个值的副本。这将导致复制所有内部成员,并且复制向量可能会很昂贵。通过将向量移出对象,我消除了这个代价。同样,将functor与state IMO一起使用通常是有缺陷的,我明白了,我没有注意到vec是在调用类的范围内声明的。谢谢你的澄清。事实上,我测试了我是这篇文章的OP,它被引用到OP的版本中,发现性能很差。我试试你的。。
    std::for_each( sizes.sizeVec.begin(), sizes.sizeVec.end(), outFunc );

    return 0;
}
// (1) struct rather than class for functor (as it contains no state).
struct Sizes
{
    // (2) Keep a reference to the vector
    std::vector<int>&    sizeVec;

    Sizes(std::vector<int>& sizeVec): sizeVec(sizeVec) {}

    // (3) The functor can now be const as the the state is external
    void operator() ( std::vector<int> const& v ) const
    {                              //  ^^^^^^  (4) Pass parameter by const reference
                                   //              This avoids an unnecessary copy.
        sizeVec.push_back( v.size() );  
    }
};

std::for_each( twodVec.begin(), twodVec.end(), Sizes(vec) );
                                         //    ^^^^^^^^^^  Call using temporary
                                         //                No need for a Size variable.
std::copy(sizes.sizeVec.begin(),
          sizes.sizeVec.end(),
          std::ostream_iterator<int>(std::cout, " ")
         );
std::for_each( twodVec.begin(), twodVec.end(), Sizes(vec) );

// becomes

std::for_each( twodVec.begin(),
               twodVec.end(), 
               [&vec] ( std::vector<int> const& v ) {  vec.push_back(v.size()); }
             );