Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ default constructor is not used at runtime, but required at compile time

Tags:

c++

Here is my code. If I remove default constructor, there will be error below. But if I add a default constructor, it will have no issues compiling and running. Wondering why? I am especially confused since default constructor is not used at all in runtime, why it is required at compile time?

#include <iostream>
#include <vector>
#include <string>

class Foo {
 public:
  //Foo();
  Foo(const std::string& name, double score);
  Foo(const Foo& other);
  Foo(Foo&& other);
  const std::string& name() const { return name_; }
  double score() const { return score_; }

 private:
  std::string name_;
  double score_;
};

/*
Foo::Foo() {
  std::cout << "In default constructor " << std::endl;
  name_ = "foo";
  score_ = 1.0;
}*/

Foo::Foo(const std::string& name, double score) : name_(name), score_(score) {
  std::cout << "In parametered constructor " << std::endl;
}

Foo::Foo(const Foo& other) {
  std::cout << "In copy constructor " << std::endl;
  name_ = other.name();
  score_ = other.score();
}

Foo::Foo(Foo&& other)
    : name_(std::move(other.name())), score_(std::move(other.score())) {
  std::cout << "In move constructor " << std::endl;
}

int main(int argc, char** argv) {
  std::vector<Foo> students;
  students.emplace_back("name1", 4.0);
  students.emplace_back("name2", 5.0);
  std::cout << "resizing begin " << std::endl;
  students.resize(1);
  for (Foo student : students) {
    std::cout << "student name: " << student.name()
              << " student score: " << student.score() << std::endl;
  }
  return 0;
}

Error message when there is no default constructor,

Error:
  required from 'static _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Foo*; _Size = long unsigned int; bool _TrivialValueType = false]'

Successful run output when there is default constructor,

In parametered constructor 
In parametered constructor 
In copy constructor 
resizing begin 
In copy constructor 
student name: name1 student score: 4
like image 937
Lin Ma Avatar asked Apr 29 '18 00:04

Lin Ma


1 Answers

The issue is your call to resize (specifically, students.resize(1)); when that line is removed, the code compiles. The issue is that resize has to initialize the new elements if it wasn't large enough, thus it needs the default constructor. If you want to shrink the size of your students without ensuring it's a sufficient size, you can use erase (Max Vollmer has a specific example).

Information on resize is available at cppreference. You're falling into the first (single argument) form.

like image 162
Stephen Newell Avatar answered Sep 22 '22 18:09

Stephen Newell