标签: most-vexing-parse

C++幽灵般的构造函数

可能重复:
为什么使用一组空括号来调用没有参数的构造函数是错误的?

让我们有这个代码

class Foo {
  Foo(int) { }
};
Run Code Online (Sandbox Code Playgroud)

然后我们有结果:

int main() {
  Foo f1 = Foo(5); // 1: OK, explicit call
  Foo f2(5); // 2: OK, implicit call
  Foo f3(); // 3: no error, "f3 is a non-class type Foo()", how so?
  Foo f4(f1); // 4: OK, implicit call to default copy constructor
  Foo f5; // 5: expected error: empty constructor missing
}
Run Code Online (Sandbox Code Playgroud)

你能解释一下案例3中发生了什么吗?

c++ constructor most-vexing-parse

11
推荐指数
3
解决办法
529
查看次数

为什么在使用()用于声明对象时不调用构造函数?

可能重复:
为什么使用一组空括号来调用没有参数的构造函数是错误的?

$ cat cons.cpp
#include <iostream>

class Matrix {
private:
    int m_count;

public:
    Matrix() {
        m_count = 1;
        std::cout << "yahoo!" << std::endl;
    }
};

int main() {
    std::cout << "before" << std::endl;
    Matrix m1();                         // <----
    std::cout << "after" << std::endl;
}
$ g++ cons.cpp
$ ./a.out
before
after
$
Run Code Online (Sandbox Code Playgroud)

语法是Matrix m1();做什么的?

我相信它是一样的Matrix m1;.显然我错了.

c++ constructor most-vexing-parse

11
推荐指数
1
解决办法
328
查看次数

10
推荐指数
2
解决办法
1040
查看次数

最烦恼的解析防止在类中初始化std :: vector <int>

C++ 11允许类内初始化:

struct Foo{
    std::vector<std::string> v{3}; // vector of 3 empty strings
};
Run Code Online (Sandbox Code Playgroud)

如果我们想要在类中初始化一个int的向量,我们会得到其他东西:

struct Foo{
    std::vector<int> v{3}; // vector of one element with value 3
};
Run Code Online (Sandbox Code Playgroud)

这个问题似乎是语言的限制,正如之前的问题所讨论的那样.但是,如果这不是类内初始化,我们将能够使用括号而不是大括号,并获得所需的结果:

std::vector<int> v(3); // vector of three zeros
Run Code Online (Sandbox Code Playgroud)

但是,由于最令人烦恼的解析,我们不能在课堂上这样做:

struct Foo{
    std::vector<int> v(3); // most vexing parse; doesn't compile
};
Run Code Online (Sandbox Code Playgroud)

当然,上面的代码是否是良好的设计实践是有争议的,因为我们可以轻松地将我们想要做的事情移动到构造函数中.但暂时把它放在一边,有没有办法执行所需的初始化,尽可能接近第一个std::string例子,这没有问题?

c++ constructor initialization most-vexing-parse c++11

10
推荐指数
1
解决办法
258
查看次数

构造函数调用机制

struct my
{
   my(){ std::cout<<"Default";}
   my(const my& m){ std::cout<<"Copy";}
   ~my(){ std::cout<<"Destructor";}
};

int main()
{
   my m(); //1
   my n(my()); //2
}
Run Code Online (Sandbox Code Playgroud)

预期产量:

1 ) Default
2 ) Copy
Run Code Online (Sandbox Code Playgroud)

实际产量:


我对构造函数调用机制的理解有什么问题?

Note 为简洁起见,我省略了头文件.

c++ constructor copy-constructor most-vexing-parse

9
推荐指数
1
解决办法
1012
查看次数

这个声明如何引用最令人烦恼的解析?

考虑以下程序:

#include <fstream>

struct A {};

int main(int argc, char** argv) {
    A a(std::fstream(argv[1]));
}
Run Code Online (Sandbox Code Playgroud)

Clang in C++ 1y模式估计MVP被调用,因此a被解析为函数声明:

clang++ -std=c++1y -O3 -Wall -Wextra -pedantic-errors -pthread main.cpp && ./a.out

main.cpp:6:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]

    A a(std::fstream(argv[1]));

       ^~~~~~~~~~~~~~~~~~~~~~~

main.cpp:6:9: note: add a pair of parentheses to declare a variable

    A a(std::fstream(argv[1]));

        ^

        (                    )
Run Code Online (Sandbox Code Playgroud)

我理解MVP,但不是在这个实例中:argv[1]显然是一个表达式,并且之前没有类型,所以如何将这一行解析为函数声明?

argv[1]在编译器已经选择将该行解析为函数声明之后,才会出现语义解释,它会将行消除歧义作为对象声明吗?或者它是一个Clang bug?或者通过对argv [ 1 ]我丢失的令牌的一些解释是完全正常的吗?

c++ most-vexing-parse

9
推荐指数
1
解决办法
943
查看次数

将匿名函数对象传递给std :: function?

这是我的问题:我定义了一个仿函数:

class A { 
 public: 
   int operator()(int a, int b) const{
    return a + b;
   }
 };
typedef function<int (int, int)> Fun;
Run Code Online (Sandbox Code Playgroud)

然后我使用匿名仿函数创建一个std :: function对象,我发现一些奇怪的东西.这是我的代码:

Fun f(A());
f(3, 4);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是错的.错误消息是:

error: invalid conversion from ‘int’ to ‘A (*)()’ [-fpermissive]
error: too many arguments to function ‘Fun f(A (*)())’
Run Code Online (Sandbox Code Playgroud)

但是,当我更改我的代码时,如下所示:

A a;
Fun f(a);
f(3, 4);
Run Code Online (Sandbox Code Playgroud)

要么

Fun f = A();
f(3, 4);
Run Code Online (Sandbox Code Playgroud)

结果是对的.那么,为什么呢?请帮我理解.谢谢.

c++ most-vexing-parse c++11

9
推荐指数
1
解决办法
506
查看次数

不寻常的编译器错误转换为void?

我正在为我正在教授的课程安排一个基于C++的作业.我有一个函数,我要向学生出口,我希望他们在他们的课程中的不同点上打电话,这样在评分期间,我们可以拦截这些电话,以确保他们在正确的时间做正确的事情.我不希望该代码在提供的启动文件中执行任何操作,因此我只给了函数一个只有一系列语句的主体,这些语句会转换所有参数void以禁止编译器有关未使用参数的警告.在这样做的过程中,我遇到了一个我以前从未见过的不寻常的编译器错误,并且对此站点的搜索没有发现任何有用的信息.

这个简化的测试用例可以最好地说明错误:

void iDontUseMyArguments(int a, int b) {
    (void) a;    // Explicit cast to void - totally fine!
    (void) b;
}

void iDontEither(int a, int b) {
    (void) a, b;  // Comma expression casted to void, though technically
                  // b isn't casted to void!
}

void norDoI(int a, int b) {
    void(a, b);   // ERROR! No idea why this isn't okay.
}

void meNeither(int a, int b) {
    (void)(a, b); // Comma expression casted to void - …
Run Code Online (Sandbox Code Playgroud)

c++ casting void comma-operator most-vexing-parse

9
推荐指数
1
解决办法
227
查看次数

构造函数不返回可用对象

我有一个构造函数的问题,它没有像我期望的那样工作.

如果我尝试像这样初始化我的类,它将工作,我得到一个可用的对象:

vector<float> v;
MyClass<2> a(v);
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试构建类似下面的类(应该是等效的),结果是非常意外的.编译或运行程序时没有错误消息/警告.但是如果你尝试在某处使用这个变量并调用它的方法(例如a.doSomething()),它就会崩溃.

我在构造函数中放了一些代码来通知我它是否被使用.事实证明,在这种情况下,构造函数中没有实际执行的代码.

MyClass<2> a(vector<float>());
Run Code Online (Sandbox Code Playgroud)

所以我想知道为什么会这样?第二次申报是非法的吗?

编辑:我将发布一些类的代码

template <int x>
class MyClass {
public:
    vector<float> v;
    MyClass<x>(vector<float> v1) {
      v = v1;
    }

};
Run Code Online (Sandbox Code Playgroud)

c++ most-vexing-parse

8
推荐指数
1
解决办法
1459
查看次数

最烦人的解析

我在Cpp Quiz 上看到了一个代码[问题 #38]

#include <iostream>

struct Foo
{
  Foo(int d) : x(d) {}
  int x;
};

int main() 
{ 
  double x = 3.14;

  Foo f( int(x) );

  std::cout << f.x << std::endl;

  return 0;
} 
Run Code Online (Sandbox Code Playgroud)

据说这段代码格式不正确,因为Foo f( int(x) );将被视为函数声明而不是 type 的对象声明Foo

据我所知,这是“最烦人的解析”的一个实例。我的问题是int(x)语句中的这种语法是什么Foo f( int(x) );意思?到目前为止,我只看到了如下函数声明:

  1. Foo f( int );

  2. Foo f( int x );

是一样的Foo f( int x );吗?

c++ most-vexing-parse

8
推荐指数
2
解决办法
1947
查看次数