初始化和分配

时间:2011-09-08 14:59:45

标签: c++ c

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

PS:如果可能的话,请在C和C ++中举例说明。

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

  

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

6 个答案:

答案 0 :(得分:15)

哦,我的。初始化和分配。嗯,这肯定是混乱!

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

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

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

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

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

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

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

在对象上的任何其他操作之前,理想情况下,对每个对象执行一次原始内存的初始化。

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

所以,这意味着当你做

    std::string s( "one" );

然后你从原始内存做了简单的构造,但是当你做

    std::string s;
    s = "two";

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

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

所以,特别是术语“初始化”取决于上下文!

只需运用一些常识来理清其他人的意思。

干杯&第h。,

答案 1 :(得分:7)

用最简单的术语来说:

int a = 0;  // initialization of a to 0
a = 1;      // assignment of a to 1

对于内置类型,它相对直接。对于用户定义的类型,它可能变得更复杂。看看this article.

例如:

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

答案 2 :(得分:5)

初始化正在创建具有特定值的实例(类型)。

int i = 0;

作业是为已创建的实例(类型)赋值。

int i;
i = 0

回答您编辑过的问题:

构造函数中的Initializing和Assignment有什么区别? &安培;
有什么好处?

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

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

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

正如您所看到的,还有额外的创作和开销。后者中的赋值,对于用户定义的类可能相当大。

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


代码示例:

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

unsigned int param () const
{
     return param_;
}

private:
     unsigned int param_;
};

在上面的例子中:

Myclass (unsigned int param) : param_ (param)

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

将成员param_初始化为值param


您何时HAVE TO使用会员初始化列表?
如果出现以下情况,您将(非常强制)使用“成员初始化程序”列表:

您的班级有参考成员
你的班级有const成员或
您的类没有默认构造函数

答案 3 :(得分:3)

初始化:给对象一个初始值:

int a(0);
int b = 2;
int c = a;
int d(c);
std::vector<int> e;

分配:为对象分配新值:

a = b;
b = 5;
c = a;
d = 2;

答案 4 :(得分:1)

在C中,初始化的一般语法是{}

struct toto { unsigned a; double c[2] };
struct toto T = { 3, { 4.5, 3.1 } };
struct toto S = { .c = { [1] = 7.0 }, .a = 32 };

S的名称称为“指定初始值设定项”,只能从C99开始使用。

  • 省略的字段会自动初始化 更正相应类型的0
  • 此语法甚至适用于double r = { 1.0 };
  • 等基本数据类型
  • 有一个catchall初始值设定项,将所有字段设置为0,即{ 0 }
  • 如果变量是静态链接的所有表达式 初始化程序必须是常量表达式

{}语法不能直接用于分配,但在C99中,您可以使用复合文字,而不是像

 S = (struct toto){ .c = { [1] = 5.0 } };

首先在RHS上创建一个临时对象并将其分配给您的对象。

答案 5 :(得分:0)

有人提到的一件事是构造函数中初始化和类字段分配之间的区别。

让我们考虑一下课程:

class Thing
{
  int num;
  char c;
public:
  Thing();
};

Thing::Thing()
  : num(5)
{
  c = 'a';
}

我们这里有一个构造函数,它将Thing::num初始化为值5,并指定&#39; a&#39;到Thing::c。在这种情况下,差异很小,但如前所述,如果你在这个例子中用intchar替换某些任意类,我们将讨论调用参数化构造函数与之间的区别。默认构造函数后跟operator=函数。