C++ 为什么允许这些默认参数?
我发现了这个问题,我完全困惑不解 答案是C++ 为什么允许这些默认参数?,c++,default-arguments,C++,Default Arguments,我发现了这个问题,我完全困惑不解 答案是b无效,“非静态成员不能用作默认参数。”。这很有道理 我不明白的是为什么其他两个都没问题。事实上,如果默认值不是常量表达式,我很难理解语义是什么 这是怎么回事?默认参数在编译时被清楚地评估。编译器只是选择当前值吗 #include <iostream> int g_x = 44; struct Foo { int m_x; static int s_x; Foo(int x) : m_x(x) {} int a
b
无效,“非静态成员不能用作默认参数。”。这很有道理
我不明白的是为什么其他两个都没问题。事实上,如果默认值不是常量表达式,我很难理解语义是什么
这是怎么回事?默认参数在编译时被清楚地评估。编译器只是选择当前值吗
#include <iostream>
int g_x = 44;
struct Foo
{
int m_x;
static int s_x;
Foo(int x) : m_x(x) {}
int a(int x = g_x) { return x + 1; }
int b(int x = m_x) { return x + 1; }
int c(int x = s_x) { return x + 1; }
};
int Foo::s_x = 22;
int main(int argc, char** argv)
{
Foo f(6);
std::cout << f.a() << std::endl;
std::cout << f.b() << std::endl;
std::cout << f.c() << std::endl;
return 0;
}
#包括
int g_x=44;
结构Foo
{
int m_x;
静态int s_x;
Foo(intx):m_x(x){}
int a(int x=g_x){返回x+1;}
int b(int x=m_x){返回x+1;}
intc(intx=s_x){返回x+1;}
};
intfoo::s_x=22;
int main(int argc,字符**argv)
{
傅f(6),;
std::cout默认参数不会在编译时计算。每次函数调用需要时都会对其进行计算。它们可以是在函数声明上下文中有效且具有适当类型的任何表达式,但不能使用任何其他参数(对于成员函数,包括this
)
这种限制是因为没有指定求值顺序,所以如果需要求值另一个参数,就无法确保参数值可用。实际上,在调用函数时会求值默认参数,这就是为什么可以这样做的原因。8.3.6
默认参数部分中(未来重点):
每次调用函数时都会计算默认参数。函数参数的计算顺序未指定。
因此,默认情况下不得使用函数的参数
参数,即使未对其求值。函数的参数
在默认参数之前声明,该参数在范围内,并且可以隐藏命名空间
和类成员名称
同一节中的以下示例为我们提供了为什么可以使用静态成员而不是非静态成员的基本原理:
[示例:下面示例中的X::mem1()声明为
格式错误,因为没有为非静态成员提供对象
用作初始值设定项的
int b;
class X {
int a;
int mem1(int i = a); // error: non-static member a
// used as default argument
int mem2(int i = b); // OK; use X::b
static int b;
};
但是,X::mem2()的声明是有意义的,因为没有对象
需要访问静态成员X::b。类、对象和
第9条中对成员进行了描述。-结束示例]
我认为这是可以理解的:
g_x和s_x在编译时可用,但this(因此this->m_x)不可用。
您可以使用一个技巧来使用m_x:
int b(int x = -1) { return x == -1 ? m_x + 1 : x + 1; }
(当然,在这种情况下-1应该是非法输入。)“默认参数在编译时会得到明确的评估”-不,不是。每次调用函数时都会计算它们。@MikeSeymour:看起来像答案,闻起来像答案……我不知道非静态成员不能用作默认参数。我不知道为什么不允许这样做。@PhilH:这是答案的一部分。现在有了正确的答案。@NeilKirk:原因与其他参数相同无法使用ETER(此
为参数的特例)。未指定求值顺序,但需要解决参数求值之间的依赖关系。但它们在编译时不可用。它们不是const
,因此值可能在运行时更改,并且对于每个函数调用都不同。Mike,您混合了两件事:值不可用,但对象(地址)不可用在编译时可用。并且有一个从中获取默认值的地址就足够了。无论如何(即使使用const或literal)你只有一个简单的地址,其中的值是。我不明白这个示例如何解释为什么非静态成员不能用作默认参数。让非静态成员a
,例如同一类的两个对象x
,比如x1
和x2
,每个对象都有自己的值,这有什么潜在问题对于a
,例如x1.a=2
和x2.a=3
,将其用作mem1
的默认参数,例如在x1.mem1()
和x2.mem1()
中。您能否提供一个示例代码,说明计算顺序很重要,在这种情况下,使用非静态默认参数将导致问题?