【问题标题】:When are the variables allocated and initialized?什么时候分配和初始化变量?
【发布时间】:2017-04-10 22:25:56
【问题描述】:

请看一下这段代码:

template <typename T>
class matrix
{
    private:
        std::vector<T> vec_;

public:
    matrix(size_t rows , size_t cols) : rows_(rows) , cols_(cols) , vec_(rows_ * cols_)
    {
    }       
    size_t rows_;
    size_t cols_;   

};

这是一种声明类的方法。我只是想知道std::vector 分配在哪里以及它在哪里被初始化?

当我声明一个变量时会发生什么?它的空间是在调用构造函数之前在堆栈中分配的,还是在构造函数中分配和初始化的?

声明一个大小为10的向量有什么区别

 std::vector<T> vec_(10);

并在构造函数中调用大小为 10 的 vec_ 的构造函数?

 matrix() : vec_(10)

我想了解如何在 C++ 中分配和初始化对象。

我也可以创建构造函数而不调用std::vector的构造函数

 matrix() {}

这里发生了什么?由于我没有调用向量的构造函数,编译器会调用它自己的构造函数吗?可以使用矢量对象吗?还是因为我将std::vector 声明为我班级中的变量而自动调用它?

还初始化为std::vector vec(10),与调用resize/reserve 的效果相同。离哪个更近?

【问题讨论】:

  • “这是一种声明类的方式”——不。这是一个模板的定义;模板是定义类的模式。

标签: c++ c++11 memory-management vector constructor


【解决方案1】:

类对象的成员按照声明的顺序进行初始化。在这种情况下,它是这个顺序:

private:
    std::vector<T> vec_;

public:
   size_t rows_;
   size_t cols_;   

所以在执行初始化列表时

matrix(size_t rows , size_t cols) : rows_(rows) , cols_(cols) , vec_(rows_ * cols_)

真正的顺序是

vec_(rows_ * cols_), rows_(rows) , cols_(cols) 

在初始化之前使用rows_cols_。坏事也会发生。

【讨论】:

  • 我不知道。谢谢!
  • 并没有真正回答这个问题,但是非常好的评论。请注意,g++ 会对此发出警告。
  • @jean - 当我写下我的答案时,这个问题得到了扩展。我会尝试添加更多信息。
  • @BoPersson 不要为我这样做,你已经得到了我的支持 :)
  • @jean - 好的,我会传递它,因为 std::vector&lt;T&gt; vec_(10); 是不允许的(语法错误),并且 std::vector&lt;T&gt; vec_{10}; 将具有不同的含义,具体取决于您的编译器是哪个版本的 initializer_list使用。
【解决方案2】:

那个代码:

private:
    std::vector<T> vec_(10);

不像 Bo 所说的那样编译。但是您可以在 c++11 中以合法且高性能的方式执行此操作(因为copy elision 是高性能的:赋值运算符很可能被转换为复制构造函数,因为对象正在这一行被初始化):

private:
    std::vector<T> vec = std::vector<T>(10);

所以,之前的构造和这个:

public: 
     matrix() : vec_(10)

做同样的事情:vec_ 将被构建一次,其中包含 10 个元素,就像 resize 所做的一样,除了它更快,因为您不必创建一个空向量 并且 em> 调整它的大小。

对于您问题的第二部分:如果您使用默认构造函数创建实例,编译器将为所有类成员调用默认构造函数,因此非常安全。

注意:POD 对象没有归零,这可能是个问题,因此最好将指针设置为nullptr,将整数设置为 0,等等...否则你会得到未初始化的值,当进入带有传递给delete的无效指针...

当然,如果其中一个成员只有非默认构造函数(需要一个参数),它将无法编译。

【讨论】:

  • 如果我在 vec_ 上调用 push_back,那将是第 11 项,对吗?
  • 绝对。这就像resize,而不是reserve
  • 所以如果我写了一个构造函数,它只为某些成员调用构造函数而不为其他成员调用构造函数,编译器会自动为我没有调用它的那些调用 cstor ?
  • 是的,所有你没有明确“构建”的成员都将使用默认构造函数来构建(如果有的话)(否则它不会编译)
猜你喜欢
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-06
  • 1970-01-01
  • 2023-03-22
  • 2019-09-22
  • 1970-01-01
相关资源
最近更新 更多