一.c++的变长参数

1、如何实现?

C++中变长参数使用可变参数模板实现。具体实现步骤如下:

  1. 在函数模板中声明可变参数模板,使用typename... Args表示可变参数包。
  2. 使用递归展开可变参数包,可以使用std::initializer_list或者递归模板函数实现。
  3. 对于每一个可变参数,可以使用模板元编程技巧std::is_same判断参数类型是否和预期的一致。

下面是一个简单示例:

#include <iostream>
#include <type_traits>

template<typename T>
void print(T arg) {
    std::cout << arg << std::endl;
}

template<typename T, typename... Args>
void print(T arg, Args... args) {
    std::cout << arg << ", ";
    print(args...);
}

template<typename... Args>
void foo(Args... args) {
    print(args...);
}

int main() {
    foo(1, 2, 3, "hello", 3.14);
    return 0;
}

输出结果为:

1, 2, 3, hello, 3.14

其中,print函数递归展开可变参数包,foo函数包装了print函数,使得可以接受任意个数和任意类型的参数。

2.如何直接访问变长参数?

可以通过使用C++标准库中的std::forward和std::tuple模板来在函数中访问变长参数中的参数。使用std::forward将变长参数中的参数转发给另一个函数,而std::tuple可以将变长参数包装成一个元组,方便在函数中使用。

下面是一个示例:

#include <iostream>
#include <tuple>
#include <type_traits>

template <typename ...Args>
void func(Args &&...args) {
    // 将变长参数包装成元组
    auto args_tuple = std::make_tuple(std::forward<Args>(args)...);

    // 访问元组中的参数
    std::cout << "There are " << std::tuple_size<decltype(args_tuple)>::value << " arguments.\
";
    std::cout << "The first argument is: " << std::get<0>(args_tuple) << "\
";
    std::cout << "The second argument is: " << std::get<1>(args_tuple) << "\
";
}

int main() {
    func(1, "hello", 3.14);
    return 0;
}

输出结果为:

There are 3 arguments.
The first argument is: 1
The second argument is: hello
The third argument is: 3.14

4. std::initializer_list和std::is_same如何使用

使用std::initializer_list

std::initializer_list的使用方法非常简单,只需要在函数参数列表中使用std::initializer_list<T>即可。下面是一个示例:

#include <iostream>
#include <initializer_list>

void print_list(std::initializer_list<int> list) {
    for (auto i : list) {
        std::cout << i << " ";
    }
    std::cout << std::endl;
}

int main() {
    print_list({1, 2, 3, 4, 5});
    return 0;
}

输出结果为:

1 2 3 4 5

在print_list函数中,使用了std::initializer_list<int>作为函数参数,可以接受一个由编译器隐式创建的数组。在main函数中,使用print_list函数并传入一个由花括号包围的整数序列,即可将整数序列传递给print_list函数。

使用std::is_same

std::is_same是一个模板元函数,用于判断两个类型是否相同。使用方法是在模板参数中传递两个类型,函数的返回值是一个constexpr bool类型的值,表示两个类型是否相同。下面是一个示例:

#include <iostream>
#include <type_traits>

template<typename T1, typename T2>
void print_if_same_type(T1 t1, T2 t2) {
    if (std::is_same<T1, T2>::value) {
        std::cout << "The types are same." << std::endl;
    } else {
        std::cout << "The types are different." << std::endl;
    }
}

int main() {
    int a = 1;
    double b = 3.14;

    print_if_same_type(a, b);
    print_if_same_type(a, 1);
    return 0;
}

输出结果为:

The types are different.
The types are same.

在print_if_same_type函数中,使用了std::is_same<T1, T2>::value判断参数T1和参数T2类型是否相同。如果相同则输出"The types are same.“,否则输出"The types are different.”。在main函数中,分别调用了print_if_same_type函数,传递了不同类型的参数

二. c++的explicit关键字的作用

explicit关键字用于禁止隐式转换。当某个构造函数被explicit修饰时,编译器将不会自动地执行类型转换,需要显式地调用构造函数进行类型转换。这样可以避免一些不必要的类型转换带来的问题

三.第一类对象

第一类对象(first-class objects)指的是在编程语言中,被视为与其他对象同等地位的对象。它们可以被赋值给变量,作为参数传递给函数,也可以从函数中返回。这些对象可以和其他对象一样被操作、处理和组合。常见的第一类对象包括整数、浮点数、字符串、数组、函数等。在许多编程语言中,函数也被视为第一类对象,这种语言通常被称为函数式编程语言。

四.非常量引用

非常量引用(non const reference)是一个指向非常量对象的引用,它可以用于修改所引用对象的值。这意味着,非常量引用可以被用作左值,也就是可以被赋值。在函数参数中使用非常量引用可以传递对象的引用并允许函数修改该对象的值。与之相对的是常量引用(const reference),它指向一个常量对象,不能用于修改所引用对象的值。

五.成员函数形参为本类对象的引用,可直接访问其私有成员

class C {
public:
    explicit C(int i) : i_(i) {}
    void swap(C& rhs) noexcept {
        using std::swap; // 内部使用标准库的swap
        v_.swap(rhs.v_);
        swap(i_, rhs.i_);
    }
    void print(void)
    {
        std::cout << i_ << std::endl;
    }

private:
    std::vector<int> v_;
    int i_;
};

int main(int argc, const char** argv) 
{
    C c1 = C(1);
    C c2 = C(2);
    c1.swap(c2);
    c1.print();
    c2.print();    
}

输出:

2
1
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐