【问题标题】:error C2228: left of '.size' must have class/struct/union错误 C2228:“.size”左侧必须有类/结构/联合
【发布时间】:2012-06-14 04:15:45
【问题描述】:

调用向量的size() 时出现此编译器错误。为什么?

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

【问题讨论】:

    标签: c++ visual-studio-2008


    【解决方案1】:

    信不信由你,这行没有声明了一个名为 resultsstd::vector 的实例,调用构造函数采用开始和结束迭代器:

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

    这实际上声明了一个名为results 的函数,它接受一个名为actualLineStream 的参数和另一个未命名的参数,两者都是std::istream_iterator&lt;int&gt; 类型。

    一般在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);
    

    【讨论】:

    • 哇..我从来没想过。
    • 我很高兴找到这篇文章。这种行为很糟糕。
    • 是的,感谢上帝,我找到了这个。我已经准备好把我的笔记本电脑扔出窗外了。
    • 非常好的答案,只是稍微修正一下:这两个参数的类型不同。第一个参数(名为actualLineStream)确实是std::istream_iterator&lt;int&gt; 类型,但第二个(未命名)是std::istream_iterator&lt;int&gt;() 类型,即"(指向)函数不带参数并返回@987654335 @"。换句话说,由于函数声明中形参的名称无关紧要,所以原行等价于std::vector&lt;float&gt; results(std::istream_iterator&lt;int&gt; param1, std::istream_iterator&lt;int&gt; (*param2)());
    • 另一种解决方案是使用大括号:Foo bar{}; IIRC,正是出于这个原因,为构造函数引入了这种语法。 herbsutter.com/2013/05/06/…
    【解决方案2】:

    我想你点击了this bugaboo。您已设法将results 声明为返回std::vector&lt;float&gt; 的新函数。如果我将声明results 的行更改为:

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

    我可以编译它(不过,使用 GCC,YMMV)

    【讨论】:

      猜你喜欢
      • 2014-01-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-03
      相关资源
      最近更新 更多