有没有什么好的理由在C++中调用默认构造函数时,一组空的圆括号(括号)无效?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
Run Code Online (Sandbox Code Playgroud)
我似乎每次都自动输入"()".是不是有一个很好的理由不允许这样做?
c++ constructor c++-faq default-constructor most-vexing-parse
例如,声明如下:
int (x) = 0;
Run Code Online (Sandbox Code Playgroud)
甚至是:
int (((x))) = 0;
Run Code Online (Sandbox Code Playgroud)
我偶然发现了这一点,因为在我的代码中我碰巧有一个类似于下面的片段:
struct B
{
};
struct C
{
C (B *) {}
void f () {};
};
int main()
{
B *y;
C (y);
}
Run Code Online (Sandbox Code Playgroud)
显然,我想构造一个对象C,然后在它的析构函数中做一些有用的东西.但是,当它发生时,编译器将其C (y);视为y带有类型的变量声明,C因此它会输出有关y重新定义的错误.有趣的是,如果我把它写成C (y).f ()或类似的东西C (static_cast<B*> (y))将按预期编译.当然,最好的现代解决方法是{}在构造函数调用中使用.
因此,当我在那之后发现,可以声明变量之类的int (x) = 0;甚至是,int (((x))) = 0;但我从未见过任何人实际使用这样的声明.所以我很感兴趣 - 这种可能性的目的是什么,因为现在我看到它只创造了类似于臭名昭着的"最令人烦恼的解析"的情况,并没有添加任何有用的东西?
我当然错过了一些东西,但我不明白为什么会编译(同时使用 g++ 和 clang++):
struct A
{
};
struct B
{
};
int main()
{
A a(B);
}
Run Code Online (Sandbox Code Playgroud)
首先,B是一种类型……而不是值。我应该如何解释这段代码?
struct X
{
X() { std::cout << "X()\n"; }
X(int) { std::cout << "X(int)\n"; }
};
const int answer = 42;
int main()
{
X(answer);
}
Run Code Online (Sandbox Code Playgroud)
我本来希望这打印
X(int),因为X(answer);可以解释为铸件从int到X,或X(answer);可以解释为变量的声明.但是,它打印X(),我不知道为什么X(answer);会调用默认构造函数.
奖励积分:我需要更改什么才能获得临时而非变量声明?
我可以做这个:
#include <iostream>
int counter;
int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(8);
}
};
Boo(8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这将编译正常,我的计数器结果是21.但是,当我尝试创建Boo传递构造函数参数而不是整数文字的对象时,我得到一个编译错误:
#include <iostream>
int counter;
int main()
{
struct Boo
{
Boo(int num)
{
++counter;
if (rand() % num < 7) Boo(num); // No default constructor
// exists for Boo
}
};
Boo(8);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如何在第二个示例中调用默认构造函数,而不是在第一个示例中调用?这是我在Visual Studio 2017上遇到的错误.
在线C++编译器onlineGDB我得到错误:
error: no matching function for call to ‘main()::Boo::Boo()’ …Run Code Online (Sandbox Code Playgroud) 我只是想知道为什么这小段代码在Visual Studio中正确编译(并且没有警告).也许结果与GCC和Clang相同,但不幸的是我现在无法测试它们.
struct T {
int t;
T() : t(0) {}
};
int main() {
T(i_do_not_exist);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 如果我有一个用户定义operator+()的:
class A
{
public:
A operator+(A)
{
return A();
}
};
Run Code Online (Sandbox Code Playgroud)
然后以下按预期工作:
A a = A() + A();
Run Code Online (Sandbox Code Playgroud)
但g ++ - 4.7给出了以下错误消息:
A a = (A()) + A();
Run Code Online (Sandbox Code Playgroud)
特别是错误消息是error: no match for ‘operator+’ in ‘+A()’.
看起来(A())在表达式中被忽略了.
我的问题是:A a = (A()) + A();应该编译,如果没有,为什么不呢?
注意:当我这样#define X (Identity())做时,这发生在我身上然后尝试了X + X.
在下面的代码中
#include <map>
#include <string>
struct P2d {
double x, y;
P2d(double x, double y) : x(x), y(y) {}
};
double bar() {
std::map<std::string, int> m;
//P2d lp = P2d(double(m["x"]), double(m["y"])); // this works
P2d lp(double(m["x"]), double(m["y"]));
return lp.x;
}
Run Code Online (Sandbox Code Playgroud)
我测试的所有编译器都同意代码(未注释版本)无效,但我不明白为什么定义
P2d lp(<double>, <double>);
Run Code Online (Sandbox Code Playgroud)
我使用的是不可接受的。
我记得规则是“如果它既可以是函数声明又可以是定义,那么它就是声明”,但我希望如果它不能是声明,那么它应该被解释为定义而不是给出错误。
我错过了什么?
我从这里得到了代码.
class Timer {
public:
Timer();
};
class TimeKeeper {
public:
TimeKeeper(const Timer& t);
int get_time()
{
return 1;
}
};
int main() {
TimeKeeper time_keeper(Timer());
return time_keeper.get_time();
}
Run Code Online (Sandbox Code Playgroud)
从它的外观来看,由于该行应该会出现编译错误:
TimeKeeper time_keeper(Timer());
Run Code Online (Sandbox Code Playgroud)
但只有在return time_keeper.get_time();存在的情况下才会发生 .
为什么这条线甚至很重要,编译器会发现time_keeper(Timer() )构造上的含糊不清.
前几天有人曾问过为什么有些东西会与clang编译,而不是与gcc编译.我直观地理解了发生了什么,并且能够帮助这个人,但它让我想知道 - 根据标准,哪个编译器是正确的?这是代码的简化版本:
#include <iostream>
#include <string>
class foo
{
public:
foo(const std::string& x):
name(x)
{ }
foo& operator()(const std::string& x)
{
std::cout << name << ": " << x << std::endl;
return (*this);
}
std::string name;
};
int main()
{
std::string x = "foo";
foo(x)("bar")("baz");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用clang ++可以很好地编译,但是g ++会出现以下错误:
runme.cpp: In function ‘int main()’:
runme.cpp:21:11: error: conflicting declaration ‘foo x’
foo(x)("bar")("baz");
^
runme.cpp:20:17: error: ‘x’ has a previous declaration as ‘std::string x’
std::string x = …Run Code Online (Sandbox Code Playgroud)