跳转至

56 C++的auto关键字

有一种方法可以让 C++自动推导出数据的类型,不管是在创建、初始化变量数据时,还是在将一个变量对另一个变量进行赋值时。

1. auto 关键字

可以自动推出 b 也是int类型。

甚至 a 的类型也可以用auto:

那问题来了,有了auto我还用写类型吗?我可以到处都用它吗?

这也得归结到编程风格问题上。同时你也需要去思考这种编程风格的优点和缺点。

2. 使用例子

std::string GetName()
{
    return "Cherno";
}

int main()
{
    std::string name = GetName();

    char a = 'a';                   // 如果只是简单赋值,写上类型会更清楚

    std::cin.get();
}

这里我可以把 name 的类型设为auto:

auto name = GetName();

这样如果api发生改变时,比如 GetName 的返回类型改为了char*,客户端不需要任何改动。但是坏处是我也不知道 api 已经改变了,它可能会破坏依赖于特定类型的代码。

3.什么时候适合用 auto?

int main()
{
    std::vector<std::string> strings;
    strings.push_back("Apple");
    strings.push_back("Orange");

    for (std::vector<std::string>::iterator it = strings.begin();
        it != strings.end();it++)
    {
        std::cout << *it << std::endl;
    }

    std::cin.get();
}

代码中iterator(迭代器)的类型太长了,可以直接用auto替换以获得更好的可读性:

另外一个例子:

class Device{};

class DeviceManager
{
private:
    std::unordered_map<std::string, std::vector<Device*>> m_Devices;
public:
    const std::unordered_map<std::string, std::vector<Device*>>& GetDevices() const
    {
        return m_Devices;
    }
};

int main()
{
    DeviceManager dm;
    const std::unordered_map<std::string, std::vector<Device*>>& devices = dm.GetDevices();
}

这里的类型相当大,这里可以做的是用alias(取别名):

using DeviceMap = std::unordered_map<std::string, std::vector<Device*>>;
    DeviceManager dm;

// 或者

typedef std::unordered_map<std::string, std::vector<Device*>> DeviceMap;

然后可以直接调用了,甚至可以把using部分挪到 DeviceManager 类中:

const DeviceMap& devices = dm.GetDevices();

这样我就得到了一个简洁且更有意义的类型。

但如果我不想用这些方法的话,就可以用auto帮助自己了;

不过要注意的是,auto不处理引用,所以不要漏掉&而造成一次复制。

这就是真实世界中两个可能比较适合使用auto的场合,比如你的变量类型非常长的话,如果变量类型只是个int你还要用 auto,那只会降低代码的可读性,在我看来没什么好处。

当进入到更加复杂的代码集,包含模板等,那种情况相当复杂,你不得不使用auto,因为你不知道类型是什么。