【问题标题】:C++ Constructors with multiple raw pointers具有多个原始指针的 C++ 构造函数
【发布时间】:2019-11-02 18:39:24
【问题描述】:

我不知道如何为具有多个原始指针的对象创建构造函数。我知道如何制作一个,但不了解多个。

我尝试在初始化期间编写一个新的构造函数,然后指定从供体对象访问的内容。

我想知道一种方法来制作多个构造函数,根据初始化顺序从一个对象中提取不同的 l 值,但是,我找不到有关如何执行此操作的信息。我在下面有一些例子。

class Movie {
   publuc:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;
Movie::Movie(const Movie &source , const Movie &source , const Movie &source , const Movie &source)
    : {movie_name = new string;
      *movie_name source;},
      {age_rating = new string;
      *age_rating source;}, 
      {view_count = new int;
      *view_count source;},
      {source.rating = new int;
      *source.rating source;}

我无法理解,我知道我遗漏了一些东西,因为这个问题必须是可以解决的。无论您身在何处,请帮助我掌握 c++。

【问题讨论】:

  • 我无法理解您的问题或您的代码。你为什么在这里使用指针?
  • publuc?那可能无法编译。

标签: c++ constructor copy-constructor object-initializers raw-pointer


【解决方案1】:

谢谢你的答案,虽然它是深夜涂鸦,但这不是家庭作业。我真的很累,并试图走在我所学的前面。虽然从好的方面来说,我还没有研究过智能指针,所以我觉得不那么愚蠢,但我只是想说谢谢你比我通常在互联网上更有建设性。

【讨论】:

  • 智能指针是你默认应该使用的,而不是在你了解了常规指针的工作原理之后应该使用的。
【解决方案2】:

您的复制构造函数全错了。它需要看起来像这样:

class Movie {
public:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   ...
};

根据Rule of 3/5/0,您还需要实现析构函数和复制赋值运算符,以及在 C++11 和更高版本中的移动构造函数和移动赋值运算符,例如:

class Movie {
public:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;

   Movie() :
      movie_name(new string),
      age_rating(new string),
      view_count(new int(0)),
      rating(new int(0))
   {
   }

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   Movie(Movie &&source) :
      movie_name(source.movie_name),
      age_rating(source.age_rating),
      view_count(source.view_count),
      rating(source.rating)
   {
      source.movie_name = nullptr;
      source.age_rating = nullptr;
      source.view_count = nullptr;
      source.rating = nullptr;
   }

   ~Movie()
   {
      delete movie_name;
      delete age_rating;
      delete view_count;
      delete rating;
   }

   Movie& operator=(const Movie &source)
   {
      if (&source != this)
      {
         *movie_name = *(source.movie_name);
         *age_rating = *(source.age_rating);
         *view_count = *(source.view_count);
         *rating = *(source.rating);
      }
      return *this;
   }

   Movie& operator=(Movie &&source)
   {
      Movie temp(std::move(source));
      std::swap(movie_name, temp.movie_name);
      std::swap(age_rating, temp.age_rating);
      std::swap(view_count, temp.view_count);
      std::swap(rating, temp.rating);
      return *this;
   }
};

您可以通过使用智能指针来降低手动管理内存分配的一些风险:

#include <memory>

class Movie {
public:
   std::unique_ptr<std::string> movie_name(new string);
   std::unique_ptr<std::string> age_rating(new string); 
   std::unique_ptr<int> view_count(new int(0));
   std::unique_ptr<int> rating(new int(0));

   Movie() = default;

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   Movie(Movie &&source) = default;

   ~Movie() = default;

   Movie& operator=(const Movie &source)
   {
      if (&source != this)
      {
         *movie_name = *(source.movie_name);
         *age_rating = *(source.age_rating);
         *view_count = *(source.view_count);
         *rating = *(source.rating);
      }
      return *this;
   }

   Movie& operator=(Movie &&source) = default;
};

但实际上,在这种情况下根本没有充分的理由使用指针。完全摆脱指针,让编译器自动生成适当的构造函数、析构函数和赋值运算符,为您完成管理内存和复制值的所有繁重工作:

class Movie {
public:
   std::string movie_name;
   std::string age_rating; 
   int view_count = 0;
   int rating = 0;

   // everything is auto-generated for you!
};

【讨论】:

  • 我故意避免给 OP 可以剪切和粘贴到他或她的作业中的东西。 :-)
【解决方案3】:

您根本不应该在这里使用原始指针。没有理由这样做。这只是一个犯大量错误的邀请。

其次,初始化器的语法非常糟糕,这根本不是语法的工作方式。我将在此处放置一个初始化器应该是什么样子的示例,以便您查看。你也误解了new 的作用。你不需要任何你正在做的任务。没有之一。

另外,您将public 拼错为publuc。而且您声明构造函数的方式对于将其声明为类成员是不正确的。

你知道,几乎所有你遇到的问题,编译器都应该给你至少含糊的错误信息,你不应该需要我们为你修复它们。

这是一个使用一些指针成员的示例类。请注意,如果您使用指针成员,尤其是作为 C++ 初学者,您几乎可以肯定做错了什么。裸指针应该是你在 C++ 中学习的最后一课,而不是第一课:

class IHaveSomePointers {
 public:
   IHaveSomePointers(bool const &mybool, int const &myint)
      : mybool_{new bool(mybool)}, myint_{new int(myint)}
   { }
   ~IHaveSomePointers() {
       delete mybool_;
       delete myint_;
   }
   IHaveSomePointers(IHaveSomePointers const &) = delete;
   void operator =(IHaveSomePointers const &) = delete;

 private:
   bool *mybool_;
   int *myint_;
};

这个类确实有一个问题。如果myint_ 的分配抛出异常,就会出现内存泄漏。这就是为什么你不在 C++ 中使用原始指针的原因,尤其是对于成员变量,尤其是如果他们将要指向的东西是用 new 分配的。

我删除了复制构造函数和赋值运算符,因为它们需要包含原始指针的类的特殊实现。我注意到您似乎一直在尝试定义自己的复制构造函数,但很难说清楚,因为您的构造函数声明非常乱码。

这个类的写法如下:

class IDontHavePointersBecauseThatsBad {
 public:
    IDontHavePointersBecauseThatsBad(bool const &mybool, int const &myint)
       : mybool_{mybool}, myint_{myint}
    { }

 private:
    bool mybool_;
    int myint_;
 };

如果您绝对必须动态分配事物,请执行以下操作:

 #include <memory>

 class ForSomeBizarreReasonIDyanmicallyAllocate {
  public:
    ForSomeBizarreReasonIDynamicallyAllocate(bool const &mybool, int const &myint)
        : mybool_{::std::make_unique<bool>(mybool)},
          myint_{::std::make_unique<int>(myint)}
    { }

  private:
    ::std::unique_ptr<bool> mybool_;
    ::std::unique_ptr<int> myint_;
 };

该类不需要析构函数来确保它删除它分配的内存。它没有潜在的内存泄漏。一切都围绕着一个更好的课程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多