Hi guys I can not solve in the following error that I find in my code:
The error indicated by the IDE refers to the move constructor. The IDE does not report me errors are when I compile it gives me error.
Scanning dependencies of target Lab_01
[ 33%] Building CXX object CMakeFiles/Lab_01.dir/main.cpp.obj
In file included from C:\Users\alex\CLionProjects\LabPDS\Lab_01\main.cpp:2:
C:\Users\alex\CLionProjects\LabPDS\Lab_01\Message.h:21: error: expected `,' or `...' before '&&' token
C:\Users\alex\CLionProjects\LabPDS\Lab_01\Message.h:21: error: invalid constructor; you probably meant `Message (const Message&)'
C:\Users\alex\CLionProjects\LabPDS\Lab_01\Message.h:23: error: **expected `,' or `...' before '&&' token**
mingw32-make.exe[3]: *** [CMakeFiles/Lab_01.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles/Lab_01.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles/Lab_01.dir/rule] Error 2
mingw32-make.exe: *** [Lab_01] Error 2
Can someone help me?
my class main.cpp in line:2 find it the error, in the class Message.h
#include <iostream>
#include "Message.h"
int main() {
Message m1(10);
std::cout << m1 << std::endl;
return 0;
}
File: Message.h
// Created by Alexandro Vassallo on 10/04/2020.
#ifndef LAB_01_MESSAGE_H
#define LAB_01_MESSAGE_H
class Message {
long id;
char* data;
int size;
static long sId;
char* mkMessage(int n);
public:
Message(); //Costruttore di Default
Message(int n); //Costruttore con un solo parametro
~Message(); //Distruttore
Message(const Message& source); //Costruttore di copia
Message(Message&& source); //Costruttore di movimento
Message& operator=(const Message& source); //Operatore di assegnazione
Message& operator=(Message&& source); //Operatore di assegnazione di movimento
long getId() const;
void setId(long id);
char *getData() const;
void setData(char *data);
int getSize() const;
void setSize(int size);
static long getSId();
static void setSId(long sId);
};
std::ostream& operator<<(std::ostream& out, const Message& m);
#endif //LAB_01_MESSAGE_H
In line 21 and line 23 above there is the move constructor and the move assigment operator.
File: Message.cpp
// Created by Alexandro Vassallo on 10/04/2020.
#include <string>
#include <iostream>
#include "Message.h"
long Message::sId = 0;
Message::Message(): id(-1), size(0){
this->data = mkMessage(0);
}
Message::Message(int n): size(n) {
this->id= sId++;
this->data = mkMessage(n);
}
Message::~Message() {
delete[] data;
}
Message::Message(const Message &source):id(source.id), size(source.size) {
this->data = new char[size];
memcpy(this->data,source.data,size);
}
Message::Message(Message &&source) {
this->id = source.id;
this->size = source.size;
this->data = source.data;
source.id = -1;
source.size = 0;
source.data = nullptr;
}
Message &Message::operator=(const Message &source) {
if(this != &source){
delete[] this->data;
this->data = nullptr;
this->size = source.size;
this->data = new char[size];
memcpy(this->data, source.data,size);
}
return *this;
}
Message &Message::operator=(Message &&source) {
if(this != &source){
delete[] this->data;
this->size = source.size;
this->data = source.data;
source.data = nullptr;
}
return *this;
}
long Message::getId() const {
return id;
}
void Message::setId(long id) {
Message::id = id;
}
char *Message::getData() const {
return data;
}
void Message::setData(char *data) {
Message::data = data;
}
int Message::getSize() const {
return size;
}
void Message::setSize(int size) {
Message::size = size;
}
long Message::getSId() {
return sId;
}
void Message::setSId(long sId) {
Message::sId = sId;
}
char* Message::mkMessage(int n) {
std::string vowels ="aeiou";
std::string consolants = "bcdfghlmnqrstvz";
char* m = new char[n+1];
for(int i = 0 ; i < n ; i++){
m[i] = i%2 ? vowels[rand()%vowels.size()]:consolants[rand()%consolants.size()];
}
m[n] = 0;
return m;
}
std::ostream& operator<<(std::ostream& out, const Message& m){
out << m.getId() << m.getSize() << m.getData();
return out;
}
Make sure you are using C++11 or later. Move semantics are not supported by older versions.
Related
I want to build a Memory Management to avoid memory leak but my code has an error that I have no idea how to fix, and how to fix the error in the code?
There: EMC_DELETE cls2; // <-- error: expected a ';'
This code is referenced from a GLSL parser (https://github.com/graphitemaster/glsl-parser/blob/main/ast.h).
// A helper function to help other to reproduce the same example.
std::string pathFolderOrFileName(const std::string &path) {
return path.substr(path.find_last_of("/\\") + 1);
}
template <typename T>
static inline void _destroy(void *self) {
((T*)self)->~T();
free(self);
}
struct Memory {
// Memory Management that's referenced from "emc-language > lexer-parser > ast.h".
Memory() : data(0), dtor(0) { }
template <typename T>
Memory(T *data, const char *file, int line) :
data((void*)data),
dtor(&_destroy<T>),
file(file),
line(line)
{}
void *data;
void (*dtor)(void*);
const char *file;
int line;
void destroy() {
dtor(data);
}
};
template <typename T>
struct Node {
void *operator new(size_t size, std::vector<Memory> *collector, const char *file, int line) throw() {
void *data = malloc(size);
if (data) {
collector->push_back(Memory((T *)data, file, line));
}
return data;
}
void operator delete(void *data, std::vector<Memory> *collector) {
auto &vec = *collector;
for (int i = 0; i < vec.size(); i++) {
if (vec[i].data == data) {
vec.erase(vec.begin() + i);
free(data);
return;
}
}
assert(0);
}
};
// Note: Never use the default 'operator new & delete' because they can cause memory leak.
#define EMC_NEW new(&g_memory, __FILE__, __LINE__) // Use this instead of using the default 'operator new'.
#define EMC_DELETE delete(&g_memory) // Use this instead of using default 'operator delete'.
//----------------------------------------------------------------------------------------------------
class MyBaseClass {
public:
int base_x, base_y;
};
class MyClass : public Node<MyClass> {
public:
int x, y;
MyClass() {
}
~MyClass() {
}
};
std::vector<Memory> g_memory;
int main() {
MyClass *cls0 = EMC_NEW MyClass();
MyClass *cls1 = EMC_NEW MyClass();
MyClass *cls2 = EMC_NEW MyClass();
EMC_DELETE cls2; // <-- error: expected a ';'
for (int i = 0; i < g_memory.size(); i++) {
auto &it = g_memory[i];
printf("%d: (file \"%s\", line %d)\n", i, pathFolderOrFileName(it.file).c_str(), it.line);
}
return 0;
}
Expected output:
0: (file "test_draft.cpp", line 79)
1: (file "test_draft.cpp", line 80)
2: (file "test_draft.cpp", line 81) this line must be removed because cls2 must be deleted.
I get a blank output. I'm a newbie and have been struggling on this for some time.
I have gotten 0 errors by the compiler.
Also what can be improved on this?
How can I get the length of const char* as an int instead of size_t without having to use static_cast.
#include <iostream>
#include <cassert>
class String
{
private:
char* Str_Buffer{};
int Str_Size{};
public:
String(const char* string = " ")
: Str_Size{ static_cast<int>(strlen(string)) }
{
Str_Buffer = new char[Str_Size];
}
String& operator=(const String& string)
{
if (this == &string)
return *this;
delete[] Str_Buffer;
Str_Size = string.Str_Size;
if (string.Str_Buffer)
{
Str_Buffer = new char[Str_Size];
for (int index{ 0 }; index < Str_Size; ++index)
Str_Buffer[index] = string.Str_Buffer[index];
}
return *this;
}
char& operator[](const int index)
{
assert(index >= 0);
assert(index < Str_Size);
return Str_Buffer[index];
}
friend std::ostream& operator<<(std::ostream& out, const String& string)
{
out << string.Str_Buffer;
return out;
}
~String()
{
delete[] Str_Buffer;
}
};
int main()
{
String word("Hello world!");
std::cout << word;
return 0;
}
I get a blank output.
You don't fill your String::Str_Buffer with meaningful data in the constructor. You could use std::strcpy() from <cstring> to do that. std::strlen() is also declared in that header file. To use std::strcpy() the memory pointed to by String::Str_Buffer needs to be one char bigger than the string you want to copy there because strings in C and C++ are zero-terminated ('\0').
How can I get the length of const char* as an int instead of size_t without having to use static_cast.
Why would you want an int? Sizes of objects in C++ are measured with values of type std::size_t (defined in several headers but when in doubt include <cstddef>). std::size_t is guaranteed to be big enough to handle all object sizes. It is for example the return type of std::strlen() and the sizeof-operator.
Your assignment operator is not exception-safe:
String& operator=(const String& string)
{
// ...
delete[] Str_Buffer; // the old state is now gone
Str_Size = string.Str_Size;
if (string.Str_Buffer)
{
Str_Buffer = new char[Str_Size]; // when new[] throws, the object
// will be in an undefined state
// ...
Possible but not elegant solution:
String& operator=(const String& string)
{
char *temp = new[string.Str_Size];
// copy string.Str_Buffer to temp
delete[] Str_Buffer;
Str_Buffer = temp;
Str_Size string.Str_Size
return *this;
}
See Copy-and-Swap for an better solution.
Resource Management
Please familiarize yourself with The Rule of Five and the Copy-and-Swap Idiom.
A starting point for a class that manages a string could look like that:
#include <cassert> // assert()
#include <cstddef> // std::size_t
#include <cstring> // std::strlen(), std::strcpy()
#include <utility> // std::swap(), std::exchange()
#include <iostream>
class string_t
{
size_t length = 0;
char *data = nullptr;
public:
string_t() = default;
string_t(char const *str)
: length { str ? std::strlen(str) : 0 },
data { new char[length + 1]{} }
{
str && std::strcpy(data, str);
}
string_t(string_t const &other) // copy constructor
: length { other.length },
data { new char[length + 1]{} }
{
other.data && std::strcpy(data, other.data);
}
string_t(string_t &&other) // move constructor
: length { std::exchange(other.length, 0) }, // steal others resources and
data { std::exchange(other.data, nullptr) } // give other a state it's
{} // destructor can work with
string_t& operator=(string_t other) // assignment operator
{ // mind: other gets copied
std::swap(length, other.length); // steal other's resources
std::swap(data, other.data); // other's destructor will
} // take care of ours.
~string_t() { delete[] data; }
std::size_t get_length() const { return length; }
char& operator[](std::size_t index)
{
assert(index < length);
return data[index];
}
// stream-insertion operator:
friend std::ostream& operator<<(std::ostream &os, string_t const &str)
{
return os << (str.data ? str.data : "");
}
};
int main()
{
string_t foo{ "Hello!" }; // char const* constructor
std::cout << foo << '\n';
string_t bar{ foo }; // copy constructor
std::cout << bar << '\n';
string_t qux{ string_t{ "World!" } }; // move constructor (from a temporary)
std::cout << qux << '\n';
bar = qux; // assignment operator
std::cout << bar << '\n';
}
First of all, you need to include for strlen. You get a blank output because the constructor does not write the input string to Str_Buffer. You may use std::copy to copy the memory to the allocated buffer.
You have to use static cast, because strlen returns std::size_t. Just change the type of Str_Size to std::size_t to get rid of the static cast.
Also take a look at the rule of five. Defining a move and copy constuctor will improve performace of your code.
See a working version of your code below:
#include <iostream>
#include <cassert>
#include <cstring>
#include <algorithm>
class String
{
private:
char* Str_Buffer;
std::size_t Str_Size;
public:
String(const char* string = " ")
: Str_Size{ strlen(string) }
{
Str_Buffer = new char[Str_Size];
std::copy(string, string + Str_Size, Str_Buffer);
}
String(const String& other)
: Str_Size(other.Str_Size)
{
Str_Buffer = new char[Str_Size];
std::copy(other.Str_Buffer, other.Str_Buffer + Str_Size, Str_Buffer);
}
String(String && other)
{
*this = std::move(other);
}
String& operator=(const String& string)
{
if (this == &string)
return *this;
delete[] Str_Buffer;
Str_Size = string.Str_Size;
if (string.Str_Buffer)
{
Str_Buffer = new char[Str_Size];
for (std::size_t index = 0; index < Str_Size; ++index)
Str_Buffer[index] = string.Str_Buffer[index];
}
return *this;
}
char& operator[](const int index)
{
assert(index >= 0);
assert(index < Str_Size);
return Str_Buffer[index];
}
friend std::ostream& operator<<(std::ostream& out, const String& string)
{
out << string.Str_Buffer;
return out;
}
~String()
{
delete[] Str_Buffer;
}
};
int main()
{
String word("Hello world!");
std::cout << word;
return 0;
}
I have searched these kind of questions, but I don't still understand why my code has error and how to implement it...
What I want to do is create a class, which can be assigned by string and char* just like std::string...http://www.cplusplus.com/reference/string/string/operator=/
string (1) string& operator= (const string& str);
c-string (2) string& operator= (const char* s);
I can write
string str1 = "haha"; //way(2)
string str2 = str1; //way(1)
So, I write this class...
class LinkedList
{
private:
ListNode *first;
public:
LinkedList():first(nullptr) {};
LinkedList(const string &str);
LinkedList& operator=(const string &str);
LinkedList& operator=(const char *s);
void Print_LinkedList();
void Push_back(char c);
// void Insert();
// void Delete();
// void Invert();
// void Clear();
};
And, the method part is...
LinkedList& LinkedList::operator=(const string &str)
{
if (str.length()%3 != 1)//legal string_input.length is 3n+1
{
cout << "LinkedList building error" << endl;
}
else
{
for (unsigned int i = 0; i < str.length(); i+=3)
{
this->Push_back(str.at(i));
}
}
return *this;
}
LinkedList& LinkedList::operator=(const char *s)
{
// if (???) //please give me some suggestions...
// {
// cout << "LinkedList building error" << endl;
// }
// else
// {
// for (???) //please give me some suggestions...
// {
// this->Push_back(???); //please give me some suggestions...
// }
// }
this->Push_back('x');
return *this;
}
And, the main part is...
int main()
{
LinkedList linkedlist1;
linkedlist1.Push_back('x');
linkedlist1.Push_back('a');
linkedlist1.Print_LinkedList();
string str_test = "H->a";
LinkedList linkedlist2(str_test);
linkedlist2.Print_LinkedList();
string str_test2 = "H->A->h->o";
LinkedList linkedlist3 = str_test2;
linkedlist3.Print_LinkedList();
LinkedList linkedlist4 = "x"; //there's an error in this line
linkedlist4.Print_LinkedList();
return 0;
}
Then, the compiler says,
"error: conversion from 'const char [2]' to non-scalar type 'LinkedList' requested|"
Could you tell me...
1.why dose my code have the compiler error?
2.how can I fix the bug?
3.some suggestions for implementing in the "LinkedList& LinkedList::operator=(const char *s){//how should I write here}"
Thanks for your help.
// stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
#include <iostream>
using namespace std;
#include "Animal.h"
// TODO: reference additional headers your program requires here
class Animal
{
private:
int itsWeight;
public:
Animal(int);
Animal();
~Animal() {}
int getWeight() const { return itsWeight; }
void Display() const;
};
template <class T>
class Array
{
private:
T *pType;
int itsSize;
const int defaultSize = 10;
public:
//constructors
Array(int itsSize = defaultSize);
Array(const Array &rhs);
~Array() { delete[] pType; }
//operators
Array& operator=(const Array&);
T& operator[](int offSet){ return pType[offSet]; }
const T& operator[](int offSet) const { return pType[offSet]; }
//methods of Access
int getSize() const { return itsSize; }
};
//constructor
template <class T>
Array<T>::Array(int size) :
itsSize(size)
{
pType = new T[size];
for (int i = 0; i < size; i++)
{
pType[i] = 0;
}
}
//copy-constructor
template <class T>
Array<T>::Array(const Array &rhs)
{
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
}
//operator prisvoeniya
template <class T>
Array<T>& Array<T>::operator=(const Array &rhs)
{
if (this == &rhs)
return *this;
delete[] pType;
itsSize = rhs.getSize();
pType = new T[itsSize];
for (int i = 0; i < itsSize; i++)
{
pType[i] = rhs[i];
}
return *this;
}
//this is the file "Animal.cpp"
#include "stdafx.h"
#include "Animal.h"
Animal::Animal()
{
itsWeight = 0;
}
Animal::Animal(int weight)
{
itsWeight = weight;
}
void Animal::Display() const
{
cout << itsWeight;
}
// the main function
#include "stdafx.h"
int_tmain(int argc, _TCHAR* argv[])
{
Array<int> theArray; //Integer array
Array<Animal> theZoo; //Animal array
Animal *pAnimal;
//filling the array
for (int i = 0; i < theArray.getSize(); i++)
{
theArray[i] = i * 2;
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
for (int j = 0; j < theArray.getSize(); j++)
{
cout << "theArray[" << j << "]:\t";
cout << theArray[j]<<"\t\t";
cout << "theZoo[" << j << "]:\t";
theZoo[j].Display();
cout << endl;
}
return 0;
}
The problem is that: The compiler gives me the errors
Error 1 error C2648: 'Array<int>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Error 2 error C2648: 'Array<Animal>::defaultSize' : use of member as default parameter requires static member
d:\documents\work\c++ files\tigrans\homework10\templates\templates\templates\animal.h 28 1 Templates
Anybody can help me to understand that. I change the
const int defaultSize=10;
to
static const int defaultSize=10
then there is not errors but in that time show Debug Assertion Failed!
This part of your code is dodgy
{
pAnimal = new Animal[i * 3];
theZoo[i] = *pAnimal;
delete pAnimal;
}
The first line allocates an array of i*3 Animals, using their default constructor (which makes an Animal with itsWeight=0). In the second line you assign the first these newly allocated Animals to theZoo[i]. Finally, the third line tries to de-allocate the Animals.
The last line contains an error, since you call delete on a pointer obtained with new [].
The whole concept of creating objects on the heap only to immediately destroy them is quite dubious -- perhaps you come from another programming language, where this is the only way to create things? First, you could simply use an automatic variable
{
Animal a; // or a(i*3);
theZoo[i] = a;
}
or yet briefer
{
theZoo[i] = Animal(i*3);
}
(Note the if you would use a std container, you could say theZoo.emplace_back(i*3);, avoiding the copy of Animal.)
I am new to c++ and I am getting errors and I am unsure why can anyone help me with this issue? thanks in advance.
Here is my header file.
#ifndef SSTACK_H
#define SSTACK_H
#include <cstdlib>
#include <string>
class sstack {
public:
// Constructor
sstack( int cap);
// Copy Constructor
sstack( const sstack& s );
~sstack( );
void push ( const std::string& s);
std::string& pop ();
std::string& top () const;
bool IsEmpty () const;
int size() const;
int getCapacity() const;
// NONMEMBER FUNCTIONS for the bag class
// Precondition: s1.size( ) + s2.size( ) <= s1.Capacity.
// Postcondition: The stack returned is the union of s1 and s2.
sstack operator +(const sstack& s2);
private:
int Capacity; // Capacity is the maximum number of items that a stack can hold
std::string* DynamicStack;
int used; // How many items are stored in the stack
};
#endif
here is the .cpp file for the sstack MY ERRORS ARE IN THIS CLASS
my first error is:
sstack.cpp:14:24: error: expected unqualified-id before 'int'
sstack.cpp:14:24: error: expected ')' before 'int'
and my second error is:
sstack.cpp:19:24: error: expected unqualified-id before 'const'
sstack.cpp:19:24: error: expected ')' before 'const'
Ive looked around online and cant seem to figure out what the issue is any ideas?
btw like I said earlier I am new to c++ so if there is anything else that looks bad or wrong or can be done better please let me know so I can learn thank you
#include "sstack.h"
// Constructor
//ERROR HERE
sstack(int cap){
test = new std::string [cap];
Capacity = cap;
}
// Copy Constructor
//ERROR 2 HERE
sstack(const sstack& s){
test = new std::string[1000];
for(int i = s.size()-1; i > 0; i--){
test[i] = *s.pop();
}//end of for
Capacity = s.getCapacity();
used = s.size();
}
~sstack(){
delete []test;
}
void push ( const std::string& s){
test[used] = *s;
used++;
}
std::string& pop (){
used-= 1;
popped = test[used];
test[used] = "";
return *popped;
}
std::string& top () const{
top = test[used--];
return *top;
}
bool IsEmpty () const{
if(used <= 0){
return true;
}else{
return false;
}
}
int size() const{
return used;
}
int getCapacity() const{
return Capacity;
}
// NONMEMBER FUNCTIONS for the bag class
// Precondition: s1.size( ) + s2.size( ) <= s1.Capacity.
// Postcondition: The stack returned is the union of s1 and s2.
sstack operator +(const sstack& s2){
int amount = used;
if(amount + s2.size() <= Capacity){
for(int i = used + s2.size()-1; i > used; i--){
test[i] = *s2.pop();
used++;
}//end of for
}//end of if
}
int Capacity = 1000; // Capacity is the maximum number of items that a stack can hold
std::string* DynamicStack;
int used = 0; // How many items are stored in the stack
std::string test[1000];
std::string popped;
std::string top;
You are missing the class scope in the member definitions:
sstack::sstack(int cap) { .... }
^^^^^^^^
void sstack::push ( const std::string& s) { .... }
^^^^^^^^