I'm receiving the message "Use of deleted function" when I combine the use of an ofstream (which I later want to use to record information) and the placement of one class inside another. Here is my minimal example:
#include <iostream>
#include <unistd.h>
#include <fstream>
class Tracker {
private:
std::ofstream tracker_file;
public:
Tracker(const std::string filename) {
tracker_file.open("tracker_file.csv", std::ios_base::app);
}
};
class Penguin {
private:
Tracker p_tracker;
public:
Penguin(
Tracker p_tracker
) : p_tracker(p_tracker) {}
};
int main()
{
Tracker penguin_tracker = Tracker("output");
Penguin gentoo(penguin_tracker);
return 1;
}
I don't understand how these are related, but if I remove the intermediate class then it works, and if I remove the ofstream it works.
In this line in the ctor of Penguin:
) : p_tracker(p_tracker) {}
You attempt to initalize the Tracker p_tracker data member.
Since you pass it an existing Tracker instance, it attempts to use the copy constuctor.
But class Tracker does not have a copy constructor. This is the "deleted function" mentioned in the error you got.
As #NathanPierson wrote in the comment below, this is because of the deleted copy constructor of the std::ofstream member variable tracker_file (and not because of the converting constructor you defined, as I originally wrote).
You could have theoretically solved it by adding a copy ctor to Tracker, something like:
Tracker(Tracker const & other)
{
// ...
}
However - as mentioned above class Tracker has a std::ofstream member which is non copyable.
So the question is what did you mean should happen in this case ?
On a side note: using the same name: p_tracker for both the class data member and the parameter passed to the constructor is a bit confusing and not recomended.
UPDATE:
To answer the question of the OP in the comment below:
If class Penguin only needs to keep a refernce to a Tracker instance, you can do the following (added "m_" prefix to members to diffrentiate them from other variables):
#include <iostream>
#include <fstream>
// No change in Tracker:
class Tracker {
private:
std::ofstream m_tracker_file;
public:
Tracker(const std::string filename) {
m_tracker_file.open("tracker_file.csv", std::ios_base::app);
}
};
// Penguin now holds a reference to Tracker:
class Penguin {
private:
Tracker & m_tracker;
public:
Penguin(
Tracker & tracker
) : m_tracker(tracker) {}
};
int main()
{
Tracker penguin_tracker("output");
Penguin gentoo(penguin_tracker);
return 0;
}
However - this solution requires you to ensure the Tracker penguin_tracker is alive as long as Tracker penguin_tracker is alive (otherwise you will have a dangling reference). In your example it is OK, just mentioned in for the general case.
Another side note: main should return 0 if all went well (not 1). See: What should main() return in C and C++?.
Related
Problem
(Apologies if I use the wrong terminology, I am used to Java constructors, and have just recently tried implementing them in C++)
I have a constructor class called FileHandler that will make a new instance of a FileHandler with two vectors inside of it (The constructor has been dulled down, as there is a lot of extraneous code not pertinent to this issue):
class FileHandler {
public:
std::vector<std::string> fullPath, fileNames;
FileHandler() {
//Creates two vectors
fullPath;
fileNames;
}
As far as I am aware, this should create two vectors inside of the instance of FileHandler, which can be manipulated normally. However, from a separate file, I call the .push_back() method (again, dulled down):
// This vector is pre-made and pre-filled before this is called,
// and I have verified it _is_ filled
std::vector<FileHandler> fileHandlers;
FileHandler testInstance = fileHandlers.at(index);
testInstance.fullPath.push_back("a_string_here");
std::cout << testInstance.fullPath.at(0);
And I get the following error (at runtime):
std::out_of_range at memory location 0x00000...
What I've tried so far
I had a suspicion that it might not like trying to push_back from outside of the constructor, so I made a separate function inside of the constructor:
void addFullPath(std::string fullPath) {
this->fullPath.push_back(fullPath);
}
However, passing a string in a similar way as before:
std::vector<FileHandler> fileHandlers;
FileHandler testInstance = fileHandlers.at(index);
testInstance.addFullPath("a_string_here");
std::cout << testInstance.fullPath.at(0);
Still gives me the same out_of_range at memory location error.
This implies (at least to me) that the second line; being the .push_back() method, is not functioning as it should. My main hypothesis at this point is that I am not instantiating the vectors in the constructor in the correct format, or that the vectors cannot be edited, however I am as of yet unsure. Please advise.
After running the following similar dummy code, everything worked normally.
There may be an error elsewhere in the extraneous code you did not show.
#ifndef UNTITLED_MYCLASS_H
#define UNTITLED_MYCLASS_H
#include <string>
#include <vector>
class MyClass {
public:
std::vector<std::string> a,b;
MyClass();
};
#endif //UNTITLED_MYCLASS_H
#include "MyClass.h"
MyClass::MyClass() {} //the vectors are dynamic and don't require initialization here
#include <iostream>
#include "MyClass.h"
int main()
{
// should not be file() which is a function call for the default constructor
MyClass file; //declares default object instance
file.a.push_back("a string");
std::cout << file.a.at(0);
return 0;
}
untitled\cmake-build-debug\untitled.exe
a string
Process finished with exit code 0
Issue solved:
My problem was the following line of code:
FileHandler testInstance = fileHandlers.at(i);
I falsely assumed that the testInstance would inherit all properties of fileHandlers.at(i), making it completely usable, however this was not the case. Replacing:
FileHandler testInstance = fileHandlers.at(index);
testInstance.fullPath.push_back("a_string_here");
std::cout << testInstance.fullPath.at(0);
With:
fileHandlers.at(index).fullPath.push_back("a_string_here");
std::cout << fileHandlers.at(index).fullPath.at(0);
Yields expected results.
Say I have a header file:
class.h
#pragma once
#include <iostream>
#include <string>
using namespace std;
class my_class
{
private:
string var1;
public:
my_class(string var1_val) { var1 = var1_val; };
};
I wish to declare a my_class variable as a global so it can be used across functions. However, it cannot be initialised outside the main function, as it requires user input to initialise. This poses a problem, as if the below code is run, I get: 'my_class': no appropriate default constructor available
source.cpp
#include <iostream>
#include <string>
#include "classes.h"
using namespace std;
my_class f;
int main(){
string inpt;
cout << "Enter var1 value: ";
cin >> inpt;
f = my_class(inpt);
}
How would I define the variable f so I could initialise it in main, but also use it in another function in the source.cpp file?
There are a few things mixed in the question. I'll try to address them individually.
The error message about the default constructor is exactly that: you are asking to instantiate an instance of that class but you only provide one way of doing so: the constructor with a string parameter.
Two ways you can deal with that "directly":
provide a default constructor, by either having it explicitly or making the string parameter optional, like my_class(string var1_val = {})
provide the said parameter at a time of instantiation: my_class f{""};
Have a variable "outside" in the global scope but initialized in main()... Also, a few ways to deal with that (personally I would advise against such a practice for various reasons, but providing options here for completeness):
Use pointers. Declare your variable as my_class * f{nullptr}; or, even better, as a smart pointer: std::unique_ptr<my_class> f; and instantiate the object in your main as either a naked pointer f = new my_class("string"); or a smart pointer f = std::make_unique<my_class>("args");
have that variable local to main() and pass it into whatever function you need it in
You might also look into using a Singleton Pattern where you have a factory function that manages your f (again, a horrible idea in this case, but providing it for completeness):
my_class & get_my_class(string s = {}){
static my_class * mc{nullptr};
if(!mc){ mc = new my_class{s}; } // <-- memory leak here unless you use unique_ptr
return *mc;
}
int main(){
// ...
auto & m{get_my_class("user input")};
// ...
}
void other_function(){
auto & f{get_my_class()};
// use f
}
The problem that you describe
as if the below code is run, I get: 'my_class': no appropriate default constructor available
is because you have declare another constructor with some parameter. In this case, compiler will not generate default constructor. You have to do it by yourself. so the class should look like:
class my_class
{
private:
string var1;
public:
my_class(){};
explicit my_class(string var1_val) :
var1(var1_val)
{};
};
Good practice is when you are making constructor with one argument mark it as explicit. Another good practice is to assign variables in constructor initialization list.
Best Regards
Just do this
my_class(string var1_val="") { var1 = var1_val; };
Provide default argument & you are good to go.
Just to get the compiler to shut up.
Although using global object is not a good solution.
That is not directly possible... a global class instance requires initialization (only types like int or double can be left initialized, but only in local scopes - as global they're always initialized - and this possibility of leaving variables uninitialized is also something many think is a design error of the C++ language - most younger languages do not provide this option as experience taught us that it's a source of nasty bugs and provides no real advantage).
What you want to do could be interpreted as a variation on what is normally called the "singleton pattern" ... i.e. providing all the modules access to a single instance of a class.
This in C++ is normally done using a function that returns a reference to the variable... for example:
------------------------------------------------------------ parms.h
...
struct Parms {
std::string user_name;
int user_age;
static Parms& get(); // Providing access to the singleton
};
-------------------------------------------------------- module1.cpp
#include "parms.h"
...
void foo() {
// access the singleton
std::cout << "Hello " << Parms::get().user_name << "\n";
}
---------------------------------------------------------- parms.cpp
#include "parms.h"
...
static Parms* parmsp;
void init_parms(const std::string& user_name, int user_age) {
// creates the singleton
parmsp = new Parms{user_name, user_age};
}
Parms& Parms::get() {
// Provide access to the singleton
if (!parmsp) {
throw std::runtime_error("Parameters not yet initialized");
}
return *parmsp;
}
I am having trouble compiling the following:
#include <QVector>
#include <QDebug>
#include <vector>
class item
{
int var;
public:
//Without default constructor this program will not compile
//item(){}
item(int value)
{
var = value;
}
int getVar()
{
return var;
}
};
int main()
{
//This code will not compile
QVector<item> y;
y.append(item(1));
qDebug() << y[0].getVar();
//std::vector however will work despite an absence of a default contructor
std::vector<item> z;
z.push_back(item(1));
qDebug() << z.at(0).getVar();
return 0;
}
To be precise the append line will not compile.
Why item has to have a default contructor in this case?
The reason why std::vector works differently lies in the fact that in vector, raw uninitialized memory is allocated and then calls copy constructor to do the copy whenever required. This process doesn't require calling default constructor for resize(). That's why there is no dependency as such on default constructor.
For more info, See AnT's answer here.
QVector requires type to be default constructible because of the way the internal function realloc() is implemented.
Source: Understanding the Qt containers
This question already has an answer here:
Copy an object and make both share a member variable (C++)
(1 answer)
Closed 4 years ago.
I need to implement the copy constructor of a class.
My requirements is that all the objects need to share the same data.
Example: if I change the name of one object, all the others object get the new object name.
This is my code:
#include <iostream>
using namespace std;
class Contact
{
public:
string name;
//Constructor:
Contact(string n){
name = n;
};
/*
// Copy constructor:
*/
};
int main(int argc, const char * argv[]) {
Contact c1("albert");
Contact c2 = c1; //create a copy of c1
c1.name = "mark"; //modify c1 name
cout << c2.name << endl; //My problem: I want this output is "mark"
return 0;
}
It is possible do it with pointers?
I try this code but I get the error:
"error: lvalue required as left operand of assignment"
// Copy constructor:
Contact (const Contact &c){
&( this -> name ) = &c.name;
}
if I change the name of one object, all the others object get the new object name.
That is a strange requirement. It does not make sense that all the instances of a class have the same name.
Disregarding the propriety of the requirement, the requirement indicates that you need some piece of data that is independent of instances of the class. It can be either a static member variable of the class or a global variable, preferably scoped to a namespace.
class Contact
{
public:
static std::string name;
//Constructor:
Contact(){}
// Copy constructor:
};
or
namespace MyApp
{
// Make sure to define it in an appropriate .cpp file.
extern std::string contact_name;
class Contact
{
public:
//Constructor:
Contact(){}
// Copy constructor:
};
}
I've searched endlessly on SE for a logical explanation for why this is happening. It is probably something very simple that I've overlooked, however I cannot spot it and would really appreciate some assistance with this.
Last week I implemented a class to read the output of a system call from a .ini file and then find and store the required information into custom objects that are then stored in a vector inside a Config class. It is a Singleton config class storing a unique_ptr for each instance of my custom class that is created.
The thing is, when I implemented this last week on my laptop, I had zero issues reading and writing to my member vector and was able to get it working exactly how I needed it. Since pulling to my desktop computer, this vector, and any STL container that I use as a member of my class, throws a segmentation fault when I try to do anything on it, even get it's size.
I've tried to shorten the code below to only include sections that actually use this vector. I have replaced my config with A, and custom class with T, and no matter where I try to use my member container, or any other test STL containers that I add to the class, I get a segfault.
For the record, I am using Qt with C++11.
Update: This example breaks on line 50 of c.cpp when debugging, and anywhere that tries to call the vector.
Debug points to this line in stl_vector.h
// [23.2.4.2] capacity
/** Returns the number of elements in the %vector. */
size_type
size() const _GLIBCXX_NOEXCEPT
/*-> this line */ { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
main.cpp
#include "c.h"
int main(int argc, char *argv[])
{
C *c = C::getInstance();
delete c;
return 0;
}
t.h - Class stores information from file
#include <string>
class T
{
public:
T();
bool Active();
std::string getA();
void setA(std::string);
private:
std::string a;
};
t.cpp
#include "t.h"
T::T()
{
}
bool T::Active()
{
if(a == "")
{
return false;
}
return true;
}
std::string T::getA()
{
return this->a;
}
void T::setA(std::string newa)
{
this->a = newa;
}
c.h - Class stores T objects and parses file for information
#include "t.h"
#include <QDebug>
#include <vector>
#include <algorithm>
#include <iostream>
#include <memory>
#include <sstream>
#include <fstream>
class C
{
public:
static C* getInstance();
private:
C();
static C* instance;
static bool init;
std::vector<std::unique_ptr<T>> t_list;
void readLines(const std::string&);
};
c.cpp
#include "c.h"
bool C::init = false;
C* C::instance = nullptr;
C::C()
{
system("echo this is a test command > a.ini");
instance->readLines("a.ini");
}
C* C::getInstance()
{
if(!init)
{
instance = new C;
init = true;
}
return instance;
}
void C::readLines(const std::string &path)
{
T* new_t;
std::ifstream file(path.c_str());
if(!file.is_open())
{
qDebug() << "Unable to open " << path.c_str();
}
std::ofstream o("test.txt");
std::string line;
while(std::getline(file, line))
{
// Split string before searching
std::stringstream ss(line);
std::string seg;
std::vector<std::string> split;
std::string left, right;
// Search patterns
size_t find_a = line.find("a");
size_t del = line.find(':');
if(find_a != std::string::npos)
{
o << "test_Size: " << t_list.size() << std::endl;
if(new_t->Active())
{
T* temp = new_t;
std::unique_ptr<T> move_t(temp);
t_list.push_back(std::move(move_t));
}
o << "test: " << t_list.size() << std::endl;
std::string n;
// Check if previous ahas any null elements
// Split string to find a
n = line.substr(line.find("a "));
n = n.substr(n.find(" ", +2));
new_t->setA(n);
}
else
{
continue;
}
}
// Add last a
T* t = new_t;
std::unique_ptr<T> move_t(t);
//t_list.push_back(std::move(move_t));
o << "a: " << t_list.back().get()->getA() << std::endl;
o << t_list.size() << std::endl;
o.close();
file.close();
}
UPDATE after code change:
I see two things now: One is that new_t in C::readlines is never initialized, so this could break when new_t->Active() is called a bit later in the function. However, I believe that the main problem you're running into is in C::C(), where it says
instance->readLines("a.ini");
At this point in the execution, C::instance is not yet initialized -- you're only just constructing the object that would later be assigned to it. Because of this, this in the readlines call is invalid, and any attempt to access object members will cause UB. This latter problem can be fixed by just calling
readLines("a.ini");
in which case the currently constructed object (that will later be instance) is used for this. I have no idea what you want to happen for the first, though, so all I can say is: If you want to have a vector<unique_ptr<T>>, you will have to create objects of type T with either new T() or (arguably preferrably) std::make_unique<T>() and put them in there.
I'll also say that this is a rather ugly way to implement a singleton in C++. I mean, singletons are never really pretty, but if you're going to do it in C++, the usual way is something like the accepted answer of C++ Singleton design pattern .
Old answer:
The problem (if it is the only one, which I cannot verify because you didn't provide an MCVE) is in the lines
T move_t = new_T;
std::unique_ptr<Adapter> ptr_t(&move_t); // <-- particularly this one
m_ts.push_back(std::move(ptr_t));
You're passing a pointer to a local object into a std::unique_ptr, but the whole purpose of std::unique_ptr is to handle objects allocated with new to avoid memory leaks. Not only will the pointer you pass into it be invalid once the scope surrounding this declaration is left, even if that weren't the case the unique_ptr would attempt to delete an object that's not on the heap at the end of its lifecycle. Both problems cause undefined behavior.
To me, it looks as though you really want to use a std::vector<T> instead of std::vector<std::unique_ptr<T>>, but that's a design issue you'll have to answer yourself.
Answering my own question here. I am trying to call a member variable from within the constructor of the object that holds it, so the vector I am trying to access is not yet instantiated and doesn't exist in memory. That is what causes the Segmentation fault to occur, I am trying to access memory that is not allocated yet, hence any call acting on any member of my C class was causing this issue.
I fixed this problem by adding a public function to the class that then calls the private readLines() function. I call that public function from the object that will take ownership of it, and since this occurs after it has been instantiated, the memory is accessible and the problem disappears.