5

我正在读一本书,它说 in 的内置类型的初始化和赋值之间没有区别Cor C++,但是 in 之类的类型string却有C++区别。为什么?为什么内置类型没有区别C

4

5 回答 5

5

因为标准类型int没有构造函数。这些

int x = 123;
int y;
y = 123;

是相同的(一开始,y会有一些随机/垃圾值)。

在创建对象时会调用其构造函数。因此,例如:

std::string s = "123";
std::string y;
y = "123";

s将立即创建并初始化,而y将被创建,其值将被初始化(基于std::string的构造函数),稍后,它们将在operator=.

于 2013-09-18T11:08:20.827 回答
4

C 并没有真正区分初始化和赋值;在 C 中,第一个赋值可以被认为是初始化,并且:

int a = 42;

int a;
a = 42;

基本相同。

在 C++ 中,初始化和赋值不同的,即使对于最基本的类型也是如此。考虑:

int
main( int argc, char** argv )
{
    switch ( argc ) {
    case 1:
        int a = 42;
        //  ...
        break;
    default:
        //  ...
    }
}

这在 C++ 中是非法的。另一方面:

int
main( int argc, char** argv )
{
    switch ( argc ) {
    case 1:
        int a;
        a = 42;
        //  ...
        break;
    default:
        //  ...
    }
}

是合法的。规则是没有代码可以“跳过”初始化到变量仍在范围内的点,但它可以跳过不包含初始化的定义。

当然,很难想象编译器会为 a 的初始化和赋值生成不同的代码int,但它们在形式上仍然是不同的。

于 2013-09-18T12:52:23.637 回答
1

Kiril Kirov已经解释了为什么标准类型的初始化和赋值是相同的,但是我想给你一个实际的例子,什么时候调用什么,所以让我们玩一下:

#include <iostream>
using std::cout;
using std::endl;

class A {
protected:
    int x;

public:
    A()
    {
        cout << "Constructor" << endl;
    }

    A(int val)
    {
        x = val;
        cout << "Parametrized constructor with x=" << x << endl;
    }

    A(const A& o)
    {
        cout << "Copy constructor with x=" << o.x << endl;
        x = o.x;
    }

    ~A()
    {
        cout << "Destructor for x=" << x << endl;
    }

    A &operator=(int val)
    {
        cout << "Assigning value x=" << val << endl;
        x = val;
        return *this;
    }

    A &operator=(const A& o)
    {
        // You are required to free previously allocated resources
        // if you're not going to reuse them
        cout << "Assigning value from parent object x=" << o.x << endl;
        x = o.x;
        return *this;
    }
};

int main()
{
    A a = 1;
    A b;
    b = 2;
    A c = a;
    b = a;
    A d(4);

    cout << endl;

    return 0;
}

将导致:

Parametrized constructor with x=1
Constructor
Assigning value x=2
Copy constructor with x=1
Assigning value from parent object x=1
Parametrized constructor with x=4

Destructor for x=4
Destructor for x=1
Destructor for x=1
Destructor for x=1

所以总结一下:

  • A a = 1;- 将调用参数化构造函数
  • A b;- 将调用空构造函数
  • b = 2;- 将调用赋值运算符
  • A c = a;- 将调用复制构造函数
  • b = a;- 将调用分配对象运算符
  • A d(4);- 将调用参数化构造函数
于 2013-09-18T11:43:12.060 回答
1

C++ 的内置原语都具有非常简单的结构:每个都存储在单个连续的内存块中。要初始化或分配这样的原语,您需要将整个新值的内容复制到原语占用的内存区域中。无需其他操作。旧值总是被此操作破坏,无论是先前分配的值还是留在内存未初始化部分的垃圾。

另一方面,类可能具有非常复杂的结构。它们可能具有指向其他对象的指针,并持有在为该类的对象分配新值时需要释放的资源。当您执行初始化时,您知道该对象还没有持有其他对象或资源,因此不需要释放任何东西。但是,当您分配现有对象时,可能需要释放它所拥有的资源和对象。这就是为什么分配不同于非基元的初始化。

于 2013-09-18T11:17:24.813 回答
0

标准数据类型没有构造函数。所以当你说,

int a = 2;

那么一个变量的值为 2。

当你说,

int b;
b = 5;

然后当 b 被创建时,它将有一些垃圾值,稍后它将被分配新值,即 5。

这不是 std::string 的情况。因为它有构造函数,所以当你创建一个类字符串的对象时,它将使用它的构造函数创建。

string str = "sample";

str将使用字符串的参数化构造函数使用值样本创建。

string str1;
str1 = "sample2";

str1将使用 string 的默认构造函数创建为空字符串,然后使用 string 的赋值运算符分配新值。

于 2013-09-18T11:18:45.740 回答