C++ 中的一些小问题, 持续补充

转载 2012年03月28日 01:07:01
  1. C++ Primer Plus 205

    char *buildstr(char c,int n)
    {
    char* pstr = new char[n + 1]
    pstr[n] = '\n';
    while(n-- > 0)
    pstr[n] = c;
    return pstr;
    }
    
    int  main
    {
    int times;
    char ch;
    char *ps = buildstr(ch,times);
    delete [] ps;
    }



    因为在 buildstr 函数中的 pstr 是局部函数 ,所以当函数结束时 pstr 被释放, 在main函数中, ps仍然指向 buildstr中的返回值 ,但是当使用完ps後 需要釋放ps,尽管之前没有在main函数中new过。


  • 2.#include <iostream>

    class B
    {
    public:
        virtual int shift(int n = 2) const { return n << 2; }
    };
    
    class D
        : public B
    {
    public:
        int shift(int n = 3) const { return n << 3; }
    };
    
    
    int main()
    {
        const D d;
        const B *b = &d;
    
    
        std::cout << b->shift() << std::endl;
    
    
        return 0;
    }




    输出结果为16  虚函数为动态绑定的,但是当有默认参数时,编译器为了省去动态绑定默认值的低效而采用了静态绑定 即 采用基类的默认参数。


  • 3.一个函数指针的例子
    C++ Primer Plus 218
    double betsy(int)
    double pam(int)
    //声明时可以省略 参数名
    
    
    double betsy(int lns)
    {
    return 0.05 * lns;
    }
    
    
    double pam(int lns)
    {
    return 0.03 * lns + 0.0004 * lns * lns;
    }
    
    
    void estimate(int lines , double(*pf)(int))
    {
    cout << lines << "lines will take"
    cout << (*pf)(lines) << " hours\n";
    }
    
    
    void main()
    {
    estimate(code , betsy);
    estimate(code , pam);
    }




    用括号括起来 *pf 是函数 pf是指向函数的指针。


    内联函数比常规函数少块, 但是占据更多的代码空间,因为内联函数可以省去函数跳转到其他函数这个操作步骤,但是取而代之的是复制函数的拷贝到每个需要使用这个函数的函数的地址附近。(编译过程中扩展代码)
    所以需要考虑 跳转和执行代码的比率,来判断使用内联函数获得的时间上的收益。


  • 4.引用 
    int rats
    int &rodents = rats
    则 rodents 为rats的别名 他们指向同一个内存地址。
    在初始化rodents的时候就必须绑定他的值 并且以后不再能改变绑定的对象


    int & rodents = rats
    等价于
    int * const rodents = &rats;


    inline const syosp & use (syosp & sysopref)
    {
    sysopref.used++;
    syosp test = sysopref;
    //return sysopref;
    return test;
    }
    
    
    int main()
    {
    syosp looper =
    {
    "test",
    "testtest",
    0
    };
    syosp ref;
    ref = use(looper);
    cout << ref.name << ref.quote << ref.used << endl;
    getchar();
    }
    



    当引用作为返回值时将直接返回返回值 而不是再把返回值拷贝到零时变量中。
    值得注意的是,当返回值为函数中的局部变量时,外部调用的函数仍能成功访问.
    或许是VS编译器的问题,这样的情况应当是被避免的。


    当返回值为引用时,最好的办法是返回一个作为参数传递给函数的引用。
    另外一个办法是 你可以在函数中new一个新的对象出来。但是就和第一例讲到的一样,你必须记得在外部delete他们。




       b.   Pointers   to   const   objects   cannot   be   deallocated   with   the   
              delete   operator.   (delete   operator   in   MSDN). 


        c.   Q1:   const   int*   pInt   =   new   int(0);   //指向常量的指针 
                      delete   pInt;    //error,看上一条b. 


  • 5.
    #include <iostream>
    
    
    template<unsigned N>
    class A
    {
    public:
        A() { std::cout << N; }
    
    
    private:
        A<N - 1> m_a;
    };
    
    
    template<>
    class A<0>
    {
    public:
        A() { std::cout << 'A'; }
    };
    
    
    int main()
    {
        { A<4>(); }
    
    
        std::cout << std::endl;
    
    
        return 0;
    }


    template 模板递归实现。自底向上。 。。


  • 6
    .#include <iostream>
    
    
    class A
    {
    public:
        explicit A(int n = 0) : m_n(n) { }
    
    
        A(const A& a)
            : m_n(a.m_n)
        {
            ++m_copy_ctor_calls;
        }
    
    
    public:
        static int m_copy_ctor_calls;
    
    
    private:
        int m_n;
    };
    
    
    int A::m_copy_ctor_calls = 0;
    
    
    A f(const A& a) { return a; }
    
    
    A g(const A a) { return a; }
    
    
    int main()
    {
        A a;
        A b = a, c(a); // 1
        std::cout << A::m_copy_ctor_calls;
    
    
        b = g(c); //2
        std::cout << A::m_copy_ctor_calls;
    
    
        const A& d = f(c); // 3
        std::cout << A::m_copy_ctor_calls << std::endl;
    getchar();
        return 0;
    }




    输出结果为 245   
    1中 当 a 赋值给 b时候 b由于新分配内存空间 调用一次拷贝构造函数 c 的初始化调用一次 当c再赋值给b 是 调用的应该是 运算符 = 的重载


    2中 参数传递拷贝一次, 返回值传递一次


    3中 返回值调用一次

  • 7
    .#include <iostream>
    #include <vector>
    
    
    class A
    {
    public:
        A(int n = 0) : m_n(n) { }
    
    
    public:
        virtual int value() const { return m_n; }
        virtual ~A() { }
    
    
    protected:
        int m_n;
    };
    
    
    class B
        : public A
    {
    public:
        B(int n = 0) : A(n) { }
    
    
    public:
        virtual int value() const { return m_n + 1; }
    };
    
    
    int main()
    {
        const A a(1);
        const B b(3);
        const A *x[2] = { &a, &b };
        typedef std::vector<A> V;
        V y;
        y.push_back(a);
        y.push_back(b);
        V::const_iterator i = y.begin();
    
    
        std::cout << x[0]->value() << x[1]->value()
                  << i->value() << (i + 1)->value() << std::endl;
        
        return 0;
    }


    输出结果1413 
    数组X中保存的是对象的地址 在调用数组中的类型的时候会根据RTTI动态找到对象的函数
    但是VECTOR容器中保存的是 父类对象A的元素 因为VECTOR是连续的内存地址, 他会把子类自动转成基类以便能封装进VECTOR中


  • 8.
    #include <iostream>
    
    
    class A
    {
    public:
        A(int n = 2) : m_i(n) { }
    
    
        ~A() { std::cout << m_i; }
    
    
    protected:
        int m_i;
    };
    
    
    class B
        : public A
    {
    public:
        B(int n) : m_x(m_i + 1) , m_a(n) { }
    
    
    public:
        ~B()
        {
            std::cout << m_i;
            --m_i;
        }
    
    
    private:
        A m_x;
        A m_a;
    };
    
    
    int main()
    {
        { B b(5); }
    
    
        std::cout << std::endl;
    
    
        return 0;
    }




    输出结果为2531  先调用b的析构函数 然后再释放B的成员变量再调用父类的析构函数

    虚函数表在类地址的最开始。

    operator int () const重载类转换运算符号
    比如 
    C c;
    int  a = (int)c;

  • 9
    .#include <iostream>
    #include <vector>
    
    
    class A
    {
    public:
        A(int n) : m_n(n) { }
        A(const A &a) : m_n(a.m_n) { ++m_copy_ctor_calls; }
        ~A() { ++m_dtor_calls; }
    
    
    private:
        int m_n;
    
    
    public:
        static int m_copy_ctor_calls;
        static int m_dtor_calls;
    };
    
    
    int A::m_copy_ctor_calls = 0;
    int A::m_dtor_calls = 0;
    
    
    int main()
    {
        const A a = 2;//1
        std::vector<A> v;
        v.reserve(2);
        v.push_back(a);
        v.push_back(1);//2
        v.push_back(a);//3
        std::cout << A::m_copy_ctor_calls << A::m_dtor_calls << std::endl;
    getchar();
        return 0;
    }


    输出结果为 5 3
    运行到1时 调用构造函数不是拷贝构造函数
    运行到2时 创建一个临时对象调用拷贝构造函数然后释放临时对象
    3时容量不够 创建新的内存空间 复制旧的到新的 释放旧的 



10. static const,virtual
class test
{
	static fun() const {}
	static virtual gun() {}
};

如果使用 是成员函数 如果使用 static 描述的 话,则不能同时为const 或者 virtual 因为,const 和 virtual内部包含了一个隐含的this指针。


未完待续..


相关文章推荐

一些小问题的解决办法(持续补充更新)

1. Q: 在Win8下安装某些软件的时候,会弹出显示扩展属性不一致的框框。 A: 在安装的时候,将输入法切换为微软输入法即可 2. Q:   Matlab中输入中文显示成方块 A: Prefer...

刚接触ubuntu,遇到的小问题总结一下(持续更新)

安装: 我装的是ubuntu12.04,最开始使用的wubi装的,简单快捷,分个盘出来,直接搞定 后来发现有个问题就是安到最后总是崩溃,安了四五次后我也崩溃了 开始用U盘安,安到最后报内部错误(...
  • lethic
  • lethic
  • 2012-06-06 02:20
  • 1365

Android studio使用的小问题,小技巧总结----持续更新中

1.android studio打开的时候每次默认进入一个project,然而更多时候我们希望能够显示新建工程的那个界面。怎么设置呢? File -Settings- 搜reopen-打开Syste...

c/c++小问题代码

  • 2012-12-05 22:46
  • 1.22MB
  • 下载

结构体和类的大小问题

...

c++空类所占内存大小问题

先看一个例子 #include using namespace std; class a {}; class b{}; class e{ public: void func1(); v...

C++继承、虚继承、虚函数类的大小问题

一、真空类 class CNull { }; 长度:1 内存结构: ?? 评注:长度其实为0,这个字节作为内容...

C++primer第八章课后变成练习的小问题

3:toupper()是将小写转换成大写的函数,但是,该函数只接受单个字符,如果使用string类型字符串时
  • erpng
  • erpng
  • 2014-05-06 15:30
  • 256

C++继承、虚继承、虚函数类的大小问题

一、真空类 class CNull { }; 长度:1 内存结构: ?? 评注:长度其实为0,这个字节作为内容没有意义,可...

Qt / C++常见小问题汇总

一、简述近期由于在工作过程中经常会遇到以前遇到过的同样的问题,当再次面对这些问题时,有时候解决起来很顺利,有时候就很尴尬,所以为何不将这些问题记录下来呢,下次再遇到不是So Easy了吗?其实说的很简...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)