C++基础教程面向对象(学习笔记(14))

匿名对象

在某些情况下,我们只需要临时变量。例如,请考虑以下情况:

#include <iostream>
int add(int x, int y)
{
    int sum = x + y;
    return sum;
}
 
int main()
{
    std::cout << add(5, 3);
 
    return 0;
}

在add()函数中,请注意sum变量实际上仅用作临时占位符变量。它没有多大贡献 - 相反,它唯一的功能是将表达式的结果传递给返回值。

实际上有一种更简单的方法来使用匿名对象编写add()函数。一个匿名的对象基本上是一个没有名字的价值。因为它们没有名称,所以除了创建它们之外没有办法引用它们。因此,它们具有“表达范围”,这意味着它们在单个表达式中被创建,评估和销毁。

这是使用匿名对象重写的add()函数:

#include <iostream>
 
int add(int x, int y)
{
    return x + y; // 创建一个匿名对象来保存并返回x + y的结果
}
 
int main()
{
    std::cout << add(5, 3);
 
    return 0;
}

x + y计算表达式时,结果将放在匿名对象中。然后通过值将匿名对象的副本返回给调用者,并销毁匿名对象。

这不仅适用于返回值,还适用于函数参数。例如,而不是这样:

void printValue(int value)
{
    std::cout << value;
}
 
int main()
{
    int sum = 5 + 3;
    printValue(sum);
    return 0;
}

我们可以这样写:

int main()
{
    printValue(5 + 3);
    return 0;
}

在这种情况下,计算表达式5 + 3以产生结果8,其被放置在匿名对象中。然后将此匿名对象的副本传递给printValue()函数(打印值8),然后销毁。

注意这使我们的代码保持清洁程度 - 我们不必使用仅使用一次的临时变量来丢弃代码。

匿名类对象

虽然我们之前的示例使用了内置数据类型,但也可以构造我们自己的类类型的匿名对象。这是通过创建像普通的对象,但省略变量名称来完成的。

Cents cents(5); // 正常变量
Cents(7); // 匿名对象

在上面的代码中,Cents(7)将创建一个匿名的Cents对象,用值7初始化它,然后销毁它。在这种情况下,这对我们没有多大帮助。那么让我们来看一个可以很好地利用它的例子:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    int getCents() const { return m_cents; }
};
 
void print(const Cents &cents)
{
   std::cout << cents.getCents() << " cents";
}
 
int main()
{
    Cents cents(6);
    print(cents);
 
    return 0;
}

请注意,此示例与使用整数的前一个示例非常相似。在这种情况下,我们的main()函数将Cents对象(名为cents)传递给函数print()。

我们可以使用匿名对象简化此程序:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    int getCents() const { return m_cents; }
};
 
void print(const Cents &cents)
{
   std::cout << cents.getCents() << " cents";
}
 
int main()
{
    print(Cents(6)); //注意:现在我们传递一个匿名的Cents值
 
    return 0;
}

如你所料,这打印:
6 cents
现在让我们来看一个稍微复杂的例子:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    int getCents() const { return m_cents; }
};
 
Cents add(const Cents &c1, const Cents &c2)
{
    Cents sum = Cents(c1.getCents() + c2.getCents());
    return sum;
}
 
int main()
{
    Cents cents1(6);
    Cents cents2(8);
    Cents sum = add(cents1, cents2);
    std::cout << "I have " << sum.getCents() << " cents." << std::endl;
 
    return 0;
}

在上面的例子中,我们使用了很多名为Cents的值。在add()函数中,我们有一个名为sum的Cents值,我们将其用作中间值,以便在返回之前保存总和。在函数main()中,我们有另一个名为sum的Cents值也用作中间值。

我们可以使用匿名值使我们的程序更简单:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    int getCents() const { return m_cents; }
};
 
Cents add(const Cents &c1, const Cents &c2)
{
    return Cents(c1.getCents() + c2.getCents()); // 返回匿名的Cents值
}
 
int main()
{
    Cents cents1(6);
    Cents cents2(8);
    std::cout << "I have " << add(cents1, cents2).getCents() << " cents." << std::endl; // 打印匿名Cents值
 
    return 0;
}

此版本的add()与上面的版本功能相同,只是它使用匿名的Cents值而不是命名变量。另请注意,在main()中,我们不再使用命名的“sum”变量作为临时存储。相反,我们匿名使用add()的返回值!

因此,我们的程序更短,更清洁,并且通常更容易遵循(一旦您理解了这个概念)。

事实上,因为cents1和cents2仅在一个地方使用,我们可以进一步匿名化:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    int getCents() const { return m_cents; }
};
 
Cents add(const Cents &c1, const Cents &c2)
{
    return Cents(c1.getCents() + c2.getCents()); // 返回匿名的Cents值
}
 
int main()
{
    std::cout << "I have " << add(Cents(6), Cents(8)).getCents() << " cents." << std::endl; // 打印匿名Cents值
 
    return 0;
}

Summary

在C ++中,匿名对象主要用于传递或返回值,而不必创建大量临时变量。动态分配的内存也是匿名完成的(这就是为什么必须将其地址分配给指针,否则我们无法引用它)。

但是,值得注意的是,匿名对象被视为rvalues(而不是lvalues,它具有地址)。这意味着匿名对象只能通过值或const引用传递或返回。否则,必须使用命名变量。

值得注意的是,因为匿名对象具有表达范围,所以它们只能使用一次。如果需要在多个表达式中引用值,则应使用命名变量。

注意:某些编译器(如Visual Studio)将允许您对匿名对象设置非const引用。这是非标准行为。

猜你喜欢

转载自blog.csdn.net/qq_41879485/article/details/82981596