【问题标题】:How to initialize an object with list in C++?如何在 C++ 中使用列表初始化对象?
【发布时间】:2017-12-02 10:08:30
【问题描述】:

抱歉,这是一个基本问题,但我找不到答案。我的问题是在哪里可以找到一些关于如何使用列表初始化对象的文档。像下面这样?

class TestClass {
public:
    int a;
    int b;
};

然后初始化一个对象:

TestClass obj = TestClass{ 1, 2};
    cout << obj.a << " " << obj.b << endl;

我只找到this页面。

似乎是方法(2),但没有提到规则是什么。例如,a,b,... 必须是公开的?我试过如果在它们之后添加一个私有 int c 它不起作用。对于 struct,我理解,我的问题是关于类的。

谢谢

【问题讨论】:

  • 结构,类,同样的东西。
  • c++中class和struct的唯一主要区别是class默认使用private,struct默认使用public成员访问。
  • 我不确定“使用列表初始化对象”是什么意思。你的意思是 std::list 对象吗?如果您的问题只是如何初始化对象,您可以在示例中使用 TestClass obj(1,2); 在堆栈上创建一个对象。如果你想在堆上创建它,你可以使用TestClass* obj = new TestClass(1,2);。使用完对象后不要忘记delete obj;
  • 是聚合初始化,不是列表初始化。我在这里找到它:en.cppreference.com/w/cpp/language/aggregate_initialization 谢谢
  • 还要注意术语“统一初始化”

标签: c++ list


【解决方案1】:

所以我发现你可以在 C++ 中用这种风格初始化任何东西,只要那个东西是一个“聚合”。现在!什么是聚合??好吧,这取决于我们在谈论什么 C++ 标准——C++11、C++14 等。这在对C++11 aggregate initialization for classes with non-static member initializers 的回答中进行了雄辩的讨论。我真的希望这会有所帮助。

【讨论】:

    【解决方案2】:

    首先,考虑基本结构。听起来您只想创建一个新的TestClass 并即时指定其初始值。

    您可以使用构造函数来做到这一点:

    /**
     * TestClass.hpp
     */
    class TestClass
    {
    public:
        int a;
        int b;
    
        TestClass(int aInitial, int bInitial);
    };
    
    /**
     * TestClass.cpp
     */
    TestClass::TestClass(int aInitial, int bInitial)
    : a(aInitial),
      b(bInitial)
    {
    
    }
    
    // ... which is the same as...
    TestClass::TestClass(int aInitial, int bInitial)
    {
        this->a = aInitial;
        this->b = bInitial;
    }
    
    /**
     * SomewhereElse.cpp
     */
    ...
    TestClass foobar(1, 2);
    std::cout << foobar.a << std::endl; // 1
    std::cout << foobar.b << std::endl; // 2
    ...
    

    但是让我们假设您已经考虑过这一点并且您实际上确实需要使用列表初始化。答案实际上就在page you mentioned, 上,让我们继续扩展吧。

    当你想用自定义类写这样的东西时......

    TestClass foobar = { 1, 2 };

    它首先需要一些手工工作。没有魔法可以自动将第 0 个索引分配给您的第一个成员,并将第一个索引分配给您的第二个成员。

    编译器需要一个接受std::initializer_list的赋值运算符或构造函数:

    /**
     * TestClass.hpp
     */
    class TestClass
    {
    public:
        int a;
        int b;
    
        TestClass(std::initializer_list<int> list); 
    };
    
    /**
     * TestClass.cpp
     */
    TestClass::TestClass(std::initializer_list<int> list)
    {
        if (list.size() != 2) {
            // Throw an error or set some defaults
        }
    
        int i = 0;
        for (int value : list) {
            if (i == 0) {
                this->a = value;
            } else {
                this->b = value;
            }
    
            i++;
        }
    }
    

    这将做你期望它做的事情。但是那个构造函数很时髦,不是吗?我们必须做那个奇怪的for 循环,因为std::initializer_list 不提供对其值的索引访问(换句话说,你不能做list[0]list[1])。

    您可以通过在构造函数中接受 std::vector(或其他类型的容器,如 std::arraystd::list 等)来使此内容更易于阅读。

    这是因为std::initializer_list那些容器中被接受为构造函数,并且可以执行隐式转换:

    /**
     * TestClass.hpp
     */
    class TestClass
    {
        int a;
        int b;
    
        TestClass(std::vector<int> values);
    };
    
    /**
     * TestClass.cpp
     */
    TestClass::TestClass(std::vector<int> values)
    {
        if (values.size() != 2) {
            // Throw an error or set some defaults
        }
    
        this->a = values[0];
        this->b = values[1];
    }
    

    【讨论】:

    • 这些都不是必需的。原始帖子的代码编译良好,根本没有任何构造函数。
    • 感谢您的精彩回答!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多