使用一个函数调用 C++ 初始化多个常量 class 成员
Initialize multiple constant class members using one function call C++
如果我有两个不同的常量成员变量,它们都需要基于同一个函数调用进行初始化,有没有办法在不调用函数两次的情况下做到这一点?
例如,分数 class 其中分子和分母是常数。
int gcd(int a, int b); // Greatest Common Divisor
class Fraction {
public:
// Lets say we want to initialize to a reduced fraction
Fraction(int a, int b) : numerator(a/gcd(a,b)), denominator(b/gcd(a,b))
{
}
private:
const int numerator, denominator;
};
这会导致时间浪费,因为 GCD 函数被调用了两次。您还可以定义一个新的 class 成员,gcd_a_b
,并首先将 gcd 的输出分配给初始化列表中的输出,但这会导致内存浪费。
一般来说,有没有一种方法可以在不浪费函数调用或内存的情况下做到这一点?您能否在初始化列表中创建临时变量?
In general, is there a way to do this without wasted function calls or memory?
是的。这可以通过 C++11 中引入的 delegating constructor 来完成。
委托构造函数是一种非常有效的方法,可以在 任何 成员变量初始化之前获取构造所需的临时值。
int gcd(int a, int b); // Greatest Common Divisor
class Fraction {
public:
// Call gcd ONCE, and forward the result to another constructor.
Fraction(int a, int b) : Fraction(a,b,gcd(a,b))
{
}
private:
// This constructor is private, as it is an
// implementation detail and not part of the public interface.
Fraction(int a, int b, int g_c_d) : numerator(a/g_c_d), denominator(b/g_c_d)
{
}
const int numerator, denominator;
};
成员变量按照它们在 class 声明中声明的顺序进行初始化,因此您可以执行以下操作(数学上)
#include <iostream>
int gcd(int a, int b){return 2;}; // Greatest Common Divisor of (4, 6) just to test
class Fraction {
public:
// Lets say we want to initialize to a reduced fraction
Fraction(int a, int b) : numerator{a/gcd(a,b)}, denominator(b/(a/numerator))
{
}
//private:
const int numerator, denominator;//make sure that they are in this order
};
//Test
int main(){
Fraction f{4,6};
std::cout << f.numerator << " / " << f.denominator;
}
无需调用其他构造函数,甚至无需创建它们。
@Drew Dormann 给出的解决方案与我的想法相似。由于 OP 从未提及无法修改 ctor,因此可以使用 Fraction f {a, b, gcd(a, b)}
:
调用
Fraction(int a, int b, int tmp): numerator {a/tmp}, denominator {b/tmp}
{
}
只有这样,才不会对函数、构造函数或其他方式进行第二次调用,所以不会浪费时间。而且这不会浪费内存,因为无论如何都必须创建临时内存,所以您不妨好好利用它。它还避免了额外的除法。
如果我有两个不同的常量成员变量,它们都需要基于同一个函数调用进行初始化,有没有办法在不调用函数两次的情况下做到这一点?
例如,分数 class 其中分子和分母是常数。
int gcd(int a, int b); // Greatest Common Divisor
class Fraction {
public:
// Lets say we want to initialize to a reduced fraction
Fraction(int a, int b) : numerator(a/gcd(a,b)), denominator(b/gcd(a,b))
{
}
private:
const int numerator, denominator;
};
这会导致时间浪费,因为 GCD 函数被调用了两次。您还可以定义一个新的 class 成员,gcd_a_b
,并首先将 gcd 的输出分配给初始化列表中的输出,但这会导致内存浪费。
一般来说,有没有一种方法可以在不浪费函数调用或内存的情况下做到这一点?您能否在初始化列表中创建临时变量?
In general, is there a way to do this without wasted function calls or memory?
是的。这可以通过 C++11 中引入的 delegating constructor 来完成。
委托构造函数是一种非常有效的方法,可以在 任何 成员变量初始化之前获取构造所需的临时值。
int gcd(int a, int b); // Greatest Common Divisor
class Fraction {
public:
// Call gcd ONCE, and forward the result to another constructor.
Fraction(int a, int b) : Fraction(a,b,gcd(a,b))
{
}
private:
// This constructor is private, as it is an
// implementation detail and not part of the public interface.
Fraction(int a, int b, int g_c_d) : numerator(a/g_c_d), denominator(b/g_c_d)
{
}
const int numerator, denominator;
};
成员变量按照它们在 class 声明中声明的顺序进行初始化,因此您可以执行以下操作(数学上)
#include <iostream>
int gcd(int a, int b){return 2;}; // Greatest Common Divisor of (4, 6) just to test
class Fraction {
public:
// Lets say we want to initialize to a reduced fraction
Fraction(int a, int b) : numerator{a/gcd(a,b)}, denominator(b/(a/numerator))
{
}
//private:
const int numerator, denominator;//make sure that they are in this order
};
//Test
int main(){
Fraction f{4,6};
std::cout << f.numerator << " / " << f.denominator;
}
无需调用其他构造函数,甚至无需创建它们。
@Drew Dormann 给出的解决方案与我的想法相似。由于 OP 从未提及无法修改 ctor,因此可以使用 Fraction f {a, b, gcd(a, b)}
:
Fraction(int a, int b, int tmp): numerator {a/tmp}, denominator {b/tmp}
{
}
只有这样,才不会对函数、构造函数或其他方式进行第二次调用,所以不会浪费时间。而且这不会浪费内存,因为无论如何都必须创建临时内存,所以您不妨好好利用它。它还避免了额外的除法。