使用指针作为成员变量复制类的构造函数

时间:2014-06-23 08:15:44

标签: c++ pointers copy-constructor

我试图为char指针和int指针编写一个复制构造函数程序。 我试图将对象a1的内容复制到a2并尝试显示a2的值。 正确显示整数指针的值,但是它不打印char指针指向的值,请让我知道这个程序有什么问题

#include <iostream>
#include<string.h>

using namespace std;
class a
{
    private:
    char *sptr;
    int *i = new int;
    public:
    a()
    {

    }
    a(char str[])
    {

        sptr = new char[strlen(str) + 1];
        strcpy( sptr, str );
        *i=5;
    }
    a(const a& source)
    {
        cout<<"copy constructor"<<endl;
        sptr = new char[strlen(source.sptr) + 1];
        strcpy( sptr, source.sptr);
        i = source.i; 
    }

    ~a()
    {
        cout<<"destructor called"<<endl;
         delete sptr;
    }

    a operator=( const a& other )
    {
        cout<<"assigment overload"<<endl;
        if(&other!=NULL)
        {
            cout<<"inside assignment";
            a tmp( other );   //  Copy first, then swap.
            //std::swap( i, tmp.i );
            // std::swap( sptr, tmp.sptr );
            // strcpy( sptr, tmp.sptr);
        }
        return *this;     //  Dtor of tmp will clean up.
    }

void display()
    {

        // while(*sptr!='\0')
        // {
        //     cout<< *sptr;
        //     sptr++;
        // }
        // cout<<endl;
        // cout<<"i="<<*i<<endl;

        for ( char const* p = sptr; *p != '\0'; ++ p ) {
            cout << *p;
        }

    }
};
int main()
{
   // cout<<"contents of a1"<<endl;
   a a1("123456789898900");
   // a1.display();
   // a a2(a1);   
   // cout<<"contents of a2"<<endl;
   // a2.display();
   a a3;
   a3 = a1;
   // a3.display();
   return 0;
}

我的修改程序:

#include <iostream>
#include<string.h>

using namespace std;
class a
{
    private:
    char *sptr;
    // int *i = new int;
    public:
    a()
    {

    }
    a(char str[])
    {

        sptr = new char[strlen(str) + 1];
        strcpy( sptr, str );
        // *i=5;
    }
    a(const a& source)
    {
        cout<<"copy constructor"<<endl;
        sptr = new char[strlen(source.sptr) + 1];
        strcpy( sptr, source.sptr);
        // i = source.i; 
    }

    ~a()
    {

         delete sptr;
         cout<<"destructor called"<<endl;
    }

    a operator=( const a& other )
    {
        cout<<"assigment overload"<<endl;
        if(&other!=NULL)
        {
            cout<<"inside assignment";
            a tmp( other );   //  Copy constructor is called
            sptr = new char[strlen(tmp.sptr) + 1];
            strcpy( sptr, tmp.sptr);
        }//destructor is called once for tmp variable when it goes out of scope
        return *this;     //   Copy constructor is called,pass by value
    }//destructor is called once for this variable when it goes out of scope

void display()
    {

        // while(*sptr!='\0')
        // {
        //     cout<< *sptr;
        //     sptr++;
        // }
        // cout<<endl;
        // cout<<"i="<<*i<<endl;

        for ( char const* p = sptr; *p != '\0'; ++ p ) {
            cout << *p;
        }
        cout<<endl;

    }
};
int main()
{
   cout<<"contents of a1"<<endl;
   a a1("123456789898900");
   a1.display();
   a a2(a1);   //copy constructor called
   cout<<"contents of a2"<<endl;
   a2.display();
   a a3;
   a3 = a1;
   cout<<"contents of a3"<<endl;
   a3.display();
   return 0;
}//destructor called for a1,a2,a3


output:
contents of a1
123456789898900
copy constructor
contents of a2
123456789898900
assigment overload
inside assignmentcopy constructor
destructor called
copy constructor
destructor called
contents of a3
123456789898900
destructor called
destructor called
destructor called

2 个答案:

答案 0 :(得分:1)

调用a1.display()时,sptr会增加到字符串的末尾。

在复制构造函数中,sptr被复制到a2,它仍然指向字符串的末尾。

我建议在显示功能中使用本地字符指针。这样可以解决问题。

答案 1 :(得分:1)

问题在于它根本不清楚语义应该是什么 是(也不是为什么你要使用int*)。你想要一份深刻的副本吗? (这可能是唯一有意义的东西,因为你的 第一个构造函数);在这种情况下,你需要实现深层次 复制在复制构造函数中;你还需要添加一个作业 运算符和析构函数。 (没有析构函数,你会泄漏 记忆。)至于你所拥有的具体错误:

sptr = (char*)malloc( sizeof( strlen( str ) ) );
  • strlen会返回size_t,因此sizeof( strlen( str ) )就是sizeof( size_t )strlen( str ) + 1相同:可能是4或8 可能只想要+ 1。 (strlen因为'\0' 并不计算最终new char[strlen(str) + 1]。)
  • 如果这是C ++,那么使用malloc并避免演员会更好。

    sptr = str;

  • 您现在已经覆盖了从sptr返回的指针, 所以你将不可避免地泄漏内存。另外,有效期 strcpy( sptr, ptr );现在取决于论证的生命周期;如果是的话 一个字符串文字,很好,但除此之外,你很可能会结束 用一个悬垂的指针。你可能想要的是什么 i,复制实际字符。

当然,我重复一个问题:为什么int是指针,而且 不只是A::A( A const& other ) : i( other.i ) // Assuming that `i` is `int`, and not `int*` : sptr( new char[strlen( other.sptr ) + 1] ) { strcpy( sptr, other.sptr ); }

在你的复制构造函数中,你不做深层复制;如果是这样的话 故意的,或者你不应该分配内存 其他构造函数,或者您需要某种引用计数。 你可能想要的是更多的东西:

A& A::operator=( A const& other )
{
    A tmp( other ):   //  Copy first, then swap.
    std::swap( i, tmp.i );
    std::swap( sptr, tmp.sptr );
    return *this;     //  Dtor of tmp will clean up.
}

A::~A()
{
    delete sptr;
}

当然,您需要一个赋值运算符和一个析构函数:

i

如果display确实是指针,那么你必须同样对待它 构造函数和析构函数。

最后,在您的'\0'功能中,您正在修改该成员 循环中的指针,表示下一次, 你会发现它指向for ( char const* p = sptr; *sptr != '\0'; ++ p ) { std::cout << *p; } 。输出应为:

sptr

(我在这里假设你这样做是为了迂腐 原因。如果'\0'指向std::cout << sptr << std::endl;字符串,那么 您只需要display中的{{1}}。)