C++对象特殊初始化及赋值

  在阅读一些C++源码的时候,我们会发现给对象初始化或赋值时用有类似“ClassA a = {1,2}”或“a = {1,2}(a是对象)”的语句。这种初始化以及赋值的表达形式让人产生疑惑:首先,它是如何给对象赋值的;其次,这种表达是不是需要ClassA有特殊的实现。这些都令人疑惑。
  网络上有人把这种赋值形式解释为ClassA类重载了赋值操作符。但是真实情况并非如此。这篇文章将对C++对象初始化以及赋值时的这种特殊用法进行一个简单的说明以及实验验证。
  
  首先观察下面的例子:

#include <iostream>
using namespace std;

template<class T, std::size_t N> 
class array 
{
    public:
        T elems[N];
        template <typename T2>
        array<T,N>& operator= (const array<T2,N>& rhs) 
        {
            cout << "operator =" << endl;
            return *this;
        }
        int &operator[](int n)
        {
            return elems[n];
        }
        int size(){return sizeof(elems)/sizeof(T);}
};

int main()
{
    array<int,6> a = {1,2,3,4,5,6};
    int sizes = a.size();
    for(int i = 0; i < sizes; i++)
        cout << a[i] << " ";
    cout << endl;
    cout << sizeof(a) << endl;

    return 0;
}

  在这个例子中有两个类array和btest,array就是我们常用的容器,因此作为一个数组的对象,我们希望它可以像基本数据结构那样去初始化。上面的代码可以正常运行,而且我们可以通过测试看到,执行结果,并没有使用赋值运算符函数。这就证明网络上说的跟赋值运算符重载是错误的。

再写一个例子:

#include <iostream>
using namespace std;

class btest
{   
public: 
    void print()
    {   
        cout << "a = " << a << " b= " << b << " c = " << c << endl;
    }
public:
    char a;
    int b;
    double c;
};

int main()
{
    btest b = {'p',56,82.342};
    btest c = b;
    b.print();
    c = {'q', 23, 43.23};
    c.print();
    return 0;
}

  这个例子,我们通过大括号的初始化方式,成功将btest类的对象b初始化,依次对对象b中的成员变量进行了赋值,使得{a,b,c}={’p’,56,82.342};而接下来的变量c,在C++98标准的编译器下,对其执行赋值操作会报错,在支持C++11即C++0x标准时,就可以正常编译运行。另外,当btest类中的成员变量改为private的时候,任何编译器都不能编译通过。
  这就引起我们的思考,我们都知道在C++中struct关键字和class关键字在语义上有很大的相通之处:1.struct也可以定义类,只是类中的默认成员都是public的;2.struct中也可以包括成员方法,这一点与类很相似;3.struct也可以在定义体中加private关键字,以强调成员对外隐藏。而struct结构体变量如果进行”structA a = {1, 3}”这样的初始化,大家就不会有太大的疑惑了。
  另外,要理解对象在内存中的存储结构。我们都知道,类的方法是被其对象所共享的,而类的成员变量则是各自拥有,因此对象的大小通常是对象的成员变量所占的内存大小;因此,其在初始化对象或赋值对象的时候,右值中大括号里的内容就会像结构体初始化一样,直接赋值到对象所占内存的成员变量中。
  还有一种需要注意到的情况就是,当类中定义有虚拟函数的时候,虚拟函数会使对象所在内存空间位于起始位置的地方保存虚表,这时这种初始化以及赋值的方法就会失效,因为这样就会有非法的数据写到虚表所在内存空间,造成虚表错误。因此,无法编译通过。
  到这里,我想这个问题说明清楚了。可能有什么纰漏,希望大家指正。

发布了29 篇原创文章 · 获赞 9 · 访问量 12万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章