初始化和分配

jsp*_*p99 16 c c++

INITIALIZATION和ASSIGNMENT之间的区别究竟是什么?

PS:如果可能的话,请特别提供C和C++中的示例.

实际上,我对这些陈述感到困惑......

C++提供了另一种初始化成员变量的方法,它允许我们在创建成员变量时而不是之后初始化成员变量.这是通过使用初始化列表完成的.使用初始化列表与执行隐式赋值非常相似.

Che*_*Alf 20

天啊.初始化和分配.嗯,这肯定是混乱!

初始化是要准备好使用.当我们谈论变量时,这意味着给变量一个有用的第一个值.一种方法是使用作业.

所以它非常微妙:赋值是进行初始化的一种方法.

赋值适用于初始化例如a int,但它不适用于初始化例如a std::string.为什么?因为该std::string对象至少包含一个指向动态分配内存的指针,并且

  • 如果对象尚未初始化,则需要将该指针设置为指向正确分配的缓冲区(用于保存字符串内容的内存块),但

  • 如果对象已经初始化,那么赋值可能必须解除分配旧缓冲区并分配新缓冲区.

因此,std::string对象的赋值运算符显然必须以两种不同的方式运行,具体取决于对象是否已经初始化!

当然,它不会以两种不同的方式表现.相反,对于std::string对象,初始化由构造函数处理.你可以说构造函数的工作是获取将代表对象的内存区域,并将那里的任意位更改为适合对象类型的东西,这表示有效的对象状态.

理想情况下,对于每个对象,在对象上的任何其他操作之前,应该从原始内存初始化一次.

而C++规则有效地保证了这一点.至少只要您不使用非常低级别的设施.有人可能会称之为C++构造保证.

所以,这意味着当你这样做

    std::string s( "one" );
Run Code Online (Sandbox Code Playgroud)

然后你从原始记忆中做了简单的构造,但是当你做的时候

    std::string s;
    s = "two";
Run Code Online (Sandbox Code Playgroud)

然后你首先构建s(对象状态表示一个空字符串),然后分配给已经初始化的对象s.

最后,这让我回答你的问题.从语言无关编程的角度来看,第一个有用的值可能是指定的值,因此在该视图中,人们将赋值视为初始化.然而,在C++技术层面,通过调用std::string默认构造函数已经完成初始化,因此在这个级别,人们认为声明是初始化,而赋值只是稍后的值更改.

所以,尤其是术语"初始化"取决于上下文!

简单地运用一些常识来理清别人可能意味着什么.

干杯&hth.,

  • @Diniz:效果就像*调用了一个没有副作用的完美复制构造函数一样。但是,编译器可以忽略该调用(将其优化掉)。实际上,不会有“C obj = f()”的复制构造函数调用,而是“f”将直接在调用者提供的存储中构造其结果,即“obj”(这称为返回值优化,或RVO)。 (2认同)
  • @Dinaiz:我的最后一个解释和更正是不好的和误导性的,我很抱歉。这是一个复杂的问题。简而言之:由于历史原因,用于初始化的`=` 符号称为**复制初始化**。复制初始化可以使用复制构造函数或移动构造函数,它们必须是可访问的。额外的复制或移动构造函数调用可以被优化掉,**省略**,即使有问题的构造函数有副作用。它通常被优化掉。 (2认同)

Cha*_*had 7

用最简单的术语来说:

int a = 0;  // initialization of a to 0
a = 1;      // assignment of a to 1
Run Code Online (Sandbox Code Playgroud)

对于内置类型,它相对直接.对于用户定义的类型,它可能变得更复杂.看看这篇文章.

例如:

class A
{
public:
   A() : val_(0)  // initializer list, initializes val_
   {}

   A(const int v) : val_(v) // initializes val_
   {}

   A(const A& rhs) : val_(rhs.val_)  // still initialization of val_
   {}

private:
    int val_;
};

// all initialization:
A a;
A a2(4);
A a3(a2);

a = a3; // assignment
Run Code Online (Sandbox Code Playgroud)


Alo*_*ave 6

初始化是创建具有特定值的实例(类型).

int i = 0;
Run Code Online (Sandbox Code Playgroud)

赋值是为已创建的实例(类型)赋值.

int i;
i = 0
Run Code Online (Sandbox Code Playgroud)

回答你编辑过的问题:

内部构造函数中的Initializing和Assignment有什么区别?&有
什么好处?

使用初始化程序列表初始化成员并在构造函数体内为其指定值之间存在差异.

通过初始化列表初始化字段时,构造函数将被调用一次.

如果使用赋值,则首先使用默认构造函数初始化字段,然后使用实际值重新分配(通过赋值运算符).

如您所见,在后者中存在创建和分配的额外开销,这对于用户定义的类可能是相当大的.

对于整数数据类型或POD类成员,没有实际开销.


代码示例:

class Myclass
{
public: 
 Myclass (unsigned int param) : param_ (param)
 {
 }

unsigned int param () const
{
     return param_;
}

private:
     unsigned int param_;
};
Run Code Online (Sandbox Code Playgroud)

在上面的例子中:

Myclass (unsigned int param) : param_ (param)
Run Code Online (Sandbox Code Playgroud)

此构造在C++中称为成员初始化列表.

它将成员初始化param_为值param.


你什么时候 HAVE TO使用成员初始化列表?
如果出现以下情况,您将(非常强制)使用"成员初始化程序"列表:

您的类有一个引用成员
您的类有一个const成员或
您的类没有默认构造函数

  • _Types_没有值,_objects_do. (2认同)