2010-11-14 166 views
16

调用vector的size()时出现此编译器错误。为什么?错误C2228:'.size'的左边必须有class/struct/union

#include <vector> 
#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <string> 
#include <cassert> 


using namespace std; 

class Vertex { 

    float firstValue; 
    float secondValue; 
    float thirdValue; 

    Vertex (float first, float second, float third){ 
      firstValue=first; 
      secondValue=second; 
      thirdValue=third; 
    } 

}; 


int main() 
{ 
    cout<<"This program loads a 3D .off object. \nEnter the name of the file that describes it "<<endl; 
    string inputFileName; 
    getline(cin, inputFileName); 

    ifstream inputFileStream; 

    inputFileStream.open(inputFileName.data()); 
    assert (inputFileStream.is_open()); 

    string actualLine; 

    for(;;){ 

     inputFileStream>>actualLine; 

     istringstream actualLineStream(actualLine); 



     std::vector<float> results(std::istream_iterator<int>(actualLineStream) 
         , std::istream_iterator<int>()); 

     int resultsIndex=0; 
     int resultsSize=results.size(); //WHY?? 

     while (resultsIndex<resultsSize){ 

     cout<<results[resultsIndex]<<endl; 
     } 


     if (inputFileStream.eof()) break; 

    } 


    ofstream outputChannel; 

    while (true){} // to keep on console view 
    return 0; 
} 

回答

48

不管你信不信,这条线声明一个名为resultsstd::vector一个实例,调用构造函数取一个开始和结束迭代器:

std::vector<float> results(std::istream_iterator<int>(actualLineStream), 
    std::istream_iterator<int>()); 

这实际上声明的函数称为results,它采用名为actualLineStream的参数和另一个未命名的参数,这两个类型均为std::istream_iterator<int>。通常在C++中,如果东西看起来像一个函数,它将被解析为一个; C++标准要求它。这实际上是为了与C向后兼容 - 但这很违反直觉,甚至有它自己的名字:"most vexing parse"。如果遇到最令人头疼的解析,一些编译器甚至会发出警告。

它关系到一个事实,即这两条线是不等价的C++:

Foo bar; // Declares an instance of Foo named bar 
Foo bar(); // Declares a function named bar that takes no parameters and returns a Foo 

要解决它,你可以其中一个参数周围添加更多的括号:

//       +--------- Note extra parentheses!! ---------+ 
//       |           | 
//       V           V 
std::vector<float> results((std::istream_iterator<int>(actualLineStream)), 
    std::istream_iterator<int>()); 

或者只需单独声明每个迭代器:

std::istream_iterator<int> resultsBegin(actualLineStream); 
std::istream_iterator<int> resultsEnd; 
std::vector<float> results(resultsBegin, resultsEnd); 
+4

哇..我从来没有想过这一点。 – andandandand 2010-11-14 03:24:58

+0

我很高兴找到这篇文章。这种行为是可怕的。 – 2011-04-21 09:59:24

+0

是的,感谢上帝,我发现了这一点。我准备把我的笔记本电脑扔出窗外。 – MikeTheLiar 2012-10-22 23:57:55

6

我想你打了this bugaboo 。您已成功将results声明为一个返回std::vector<float>的新函数。如果我改变声明results到行:

std::vector<float> results = std::vector<float>(std::istream_iterator<int>(actualLineStream), std::istream_iterator<int>()); 

我可以编译这个(与海湾合作委员会,不过,情况因人而异)

相关问题