cont = cont;
I don't know how to convert cont to cont type pointer.
If I do like this : this->cont = (char*)cont;
In deconstructor I have exception error.
So is it good to convert const char to char* or I need to do better (but how?) ?
And I have to have dynamic allocate.
#include "pch.h"
#include <iostream>
#include <stdio.h>
using namespace std;
class Matrix {
private:
int x;
char *cont;
public:
Matrix(){
cout << "aa";
}
Matrix(const char *cont) {
this->cont = cont;
}
~Matrix() {
delete cont;
}
};
int main()
{
Matrix("__TEXT__");
system("pause");
return 0;
}
this->cont = cont;
Is "wrong", as in, it doesn't actually copy the data; that's also why delete in your destructor if failing. Your answer mentions "I have to have dynamic allocate.", so I presume that's what you actually wanted. In this case, simply use std::string:
class Matrix {
private:
int x;
std::string cont; // <--- changed type
public:
Matrix(){
cout << "aa";
}
Matrix(const char *cont)
: cont(cont) { // <--- this actually copies
}
};
first you have to allocate space for a pointer to char using new .
And in the destructor deallocate that space " delete [] cont " instead of "delete cont" .
but it will be a good choice to use std::string instead of char []
Related
I have a class that must return a constant view of some pointers to the upper layers of software.
Internally, the pointers must be non-const, because the class will need to manipulate the objects internally.
I don't see any option for providing this const view of the pointers to a higher level client, without making a copy of all the pointers. This seems wasteful. What if I was managing millions of objects?
Is there a better way?
Here is some example code:
#include <vector>
#include <iostream>
class example {
public:
example() {
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
// I want to do this, but compiler will not allow
// error: could not convert ‘((example*)this)->example::bytePtrs_’ from ‘std::vector<char*>’ to ‘std::vector<const char*>’
std::vector<const char*> getPtrs() {
return bytePtrs_;
}
// Must make wasteful copy
std::vector<const char*> getPtrs() {
std::vector<const char*> ret;
for (auto &ptr : bytePtrs_)
ret.push_back(ptr);
return ret;
}
private:
std::vector<char*> bytePtrs_;
};
int main() {
example e;
std::vector<const char*> bytePtrs = e.getPtrs();
std::cout << bytePtrs[0] << std::endl;
}
You can do this using std::experimental::propagate_const.
That will forward the constness of the pointer onto the pointed-to object.
#include <experimental/propagate_const>
class example {
public:
// using vector = std::vector<char*>>;
using vector = std::vector<std::experimental::propagate_const<char*>>;
example() {
bytePtrs.push_back(new char);
*bytePtrs[0] = '$';
}
vector const& getPtrs() const {
return bytePtrs;
}
private:
vector bytePtrs;
};
int main()
{
example e;
example::vector const& bytePtrs = e.getPtrs();
// dereference this or add a null terminator
std::cout << *bytePtrs[0] << std::endl; // fine and dandy
*bytePtrs[0] = 'x'; // compile error
}
Consider returning a proxy object when you only want to permit const access, something like this (edited to fix the massive hole in the original code pointed out by #alagner!):
#include <iostream>
#include <vector>
template <class T> class proxy_vector
{
public:
proxy_vector (const std::vector<T *> &v) : m_v (v) { }
size_t size () { return m_v.size (); }
const T * const &operator[] (size_t i) const { return m_v [i]; }
// ... more functions as needed
private:
const std::vector <T *> &m_v;
};
class example
{
public:
example() : m_pv (bytePtrs_)
{
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
const proxy_vector <char> &getPtrs() { return m_pv; }
private:
std::vector<char*> bytePtrs_;
proxy_vector <char> m_pv;
};
int main()
{
example e;
auto &bytePtrs = e.getPtrs ();
// *bytePtrs [0] = 'x'; // uncomment to show that this code now actually works as intended!
std::cout << bytePtrs[0] << "\n";
}
A decent compiler should optimise most, if not all, of this away. Add access methods to proxy vector as needed, I doubt you will need many.
Demo (seems to work fine in C++11).
What #alagner suggests should also work and might be simpler. I haven't thought that through.
As the OP has pointed out in one of the comments, this is the API the code needs to comply to:
https://github.com/Xilinx/Vitis-AI/blob/master/src/Vitis-AI-Runtime/VART/vart/runner/include/vart/runner.hpp#L157
So by design it returns by copy, which is unavoidable really, thus what really can be done is this:
#include <vector>
#include <iostream>
class example {
public:
example() {
bytePtrs_.push_back(new char);
*bytePtrs_[0] = '$';
}
// Returning by value
// so shallow copy of objects is expected
// i.e. the pointers are copied
std::vector<const char*> getPtrs() {
return std::vector<const char*>(bytePtrs_.begin(), bytePtrs_.end());
}
private:
std::vector<char*> bytePtrs_;
};
int main() {
example e;
std::vector<const char*> bytePtrs = e.getPtrs();
std::cout << bytePtrs[0] << std::endl;
}
This is one of the very few cases where reinterpret_cast<> could be allowed into the code I think: since the std::vector<char *> and const std::vector<const char*>& are assumed to be compatible in memory anyways, you might cast. Thus, getPtrs() could actually return reinterpret_cast<const std::vector<const char*>&>(bytePtrs_);. To be clear: this is an optimization that relies on concrete ABI details (ItaniumABI et. al.), not generic standard C++, but I'm not yet aware of any architecture where it wouldn't work.
In c++20 and later, you might consider checking std::ranges::view.
Here is a simple code:
#include <iostream>
#include <string>
typedef struct Car{
std::string model;
} Car;
std::string get_model() {
std::string str = "Maserati";
return str;
}
int main() {
const int nCars = 2;
//Car *list = new Car[nCars]; // works everywhere g++/VC++
Car *list = (Car *)malloc(nCars * sizeof(Car)); // works in g++, not VC++
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
// delete[] list;
free(list);
return 0;
}
There is no problem when I used malloc() or new in g++. However, malloc() does not work in Visual C++. Should I use new always when I allocate the C++ class object?
(a debtor)<><
You are allocating memory without calling a constructor or calling the destructor when the object is about to be removed. This is what new[] and delete[] does for you, so use them - or better yet, use smart pointers - or even better, a standard container, like std::vector to keep the objects for you.
Your code with the missing parts added:
#include <iostream>
#include <string>
struct Car {
std::string model;
Car() { std::cout << "ctor\n"; }
~Car() { std::cout << "dtor\n"; }
};
int main() {
const int nCars = 2;
// allocate memory
Car *list = (Car *)malloc(nCars * sizeof(Car));
// manually calling constructors
for(int i=0; i<nCars; ++i) {
new(&list[i]) Car();
}
// use objects here
// manually calling destructors
for(int i=0; i<nCars; ++i) {
list[i].~Car();
}
// freeing memory
free(list);
}
Compare with using new[] and delete[]:
int main() {
const int nCars = 2;
// create cars
Car* list = new Car[nCars];
// use objects here
// delete cars
delete[] list;
}
Compare with using a container:
int main() {
const int nCars = 2;
// create cars
std::vector<Car> list(nCars);
// use objects here
}
Yes.
While it is wrong to say, "Never use malloc() in C++," it is definitely true that you should never use malloc() to instantiate a class.
Keep in mind that C++ is, in a sense, a hybrid language in that it effectively supports an almost complete subset of C and adds the superset of C++ functionality. malloc() has a role to play when using built-in types like int, char, float, etc.
For objects, however, new must be used. It might be true that you have found that malloc() works in many cases, but new and delete will cause constructors and destructors to be called, which will never happen with malloc() and free().
The problem here is because you're allocating a memory for the std::string of your Car struct but do not call the std::string constructor.
You should call a placement new for each item in the array to call the constructor and initialize the std::string field in the Car struct:
int main() {
const int nCars = 2;
Car* list = (Car *)malloc(nCars * sizeof(Car));
for (int i = 0; i < nCars; ++i)
new(&list[i])Car();
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
}
-- ORIGINAL ANSWER --
Here's my original answer (which is inorrect due to an extra overhead that may be required for arrays: https://en.cppreference.com/w/cpp/language/new#Allocation)
If you have to use malloc then I suggest you use a in-place constructor with the returned memory block:
int main() {
const int nCars = 2;
Car *list = new (malloc(nCars * sizeof(Car)))Car[nCars];
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
return 0;
}
Dear StackOverFlowers,
I'm having trouble passing a const char* [] to an object. The scenario is as follows.
I have a class UlamScreen which contains a const char* [] with several strings. UlamScreen also contains an object homeScreenMenu.
class UlamScreen {
const char* homeScreenText[5] = {"EVA dun", "Sabine", "TPU dun", "test Wout",
UlamScreenMenu homeScreenMenu;
};
class UlamScreenMenu {
private:
const char* _menuText[];
public:
UlamScreenMenu(const char*[]);
void drawMenu();
};
I want to pass the const char* [] to UlamScreenMenu so I can use it in a member function called void drawMenu, like this:
void UlamScreenMenu::drawMenu() {
for (int i = 0; i < menuItems; i++) {
tft.println(_menuText[i]);
}
}
I passed it to UlamScreenMenu's constructor like this:
UlamScreen::UlamScreen() : homeScreenMenu(homeScreenText) {
}
UlamScreenMenu::UlamScreenMenu(const char* menuText[], int length) {
for(int i = 0; i < length; i++) {
_menuText[i] = menuText[i];
}
}
I thought this would work, but for some reason, it does not. tft.println(_menuText[i]); used with void drawMenu does not send anything to my tft screen. When I use tft.println(_menuText[i]); from within the UlamScreen class it works perfectly.
Just to be clear, I can use the tft object within the UlamScreenMenu class because other functions like tft.drawRect() are working correctly.
What is wrong with this way of passing the const char* []? Thanks in advance.
In C++, you can't declare a member variable of type const char* x[], since this would denote a flexible array member. Flexible array members are a C-feature allowing the last member of a struct to be an array of varying size (cf., for example, Arrays of unknown size / flexible array members). Having parameters of type const char* x[] in functions, however, is supported and has basically the same meaning as const char** x.
If you stick to a member of type const char**, then you'll have to handle memory management in that class. This means: take care of allocating, deallocating, copying, moving, copy-assigning, and move-assigning objets of that class (cf, for example, the rule of 0/3/5).
If - as suggested in the comments - you use standard library collections, e.g. std::vector, these classes will do all this stuff in a reliable manner for you. See the following example illustrating the difference between both:
Note that the C++-version probably would not even take a const char*[]-parameter but directly a const std::vector<const char*> &x-parameter. But I kept the const char*[]-parameter in the constructor to provide the same interface in both variants:
// Variant 1: "old" C-style:
class Menu {
public:
Menu(const char* x[], int length) {
m_x = new const char*[length];
m_length = length;
for (int i=0; i<length; i++) {
m_x[i] = x[i];
}
}
~Menu() {
delete[] m_x;
}
// TODO: implement copy- and move constructors + copy- and move assignments
// ...
void print() {
for (int i=0; i<m_length; i++) {
std::cout << m_x[i] << std::endl;
}
}
private:
const char** m_x = nullptr;
int m_length;
};
#include <vector>
// Variant 2: a C++- way:
class Menu2 {
public:
Menu2(const char* x[], int length) {
m_x.assign(x, x+length);
}
void print() {
for (auto s : m_x) {
std::cout << s << std::endl;
}
}
// Menu2 does not manage memory on its own, hence:
// No special copy/move - constructors/assignments to be implemented.
// No special destructor necessary
private:
std::vector<const char*> m_x;
};
int main() {
const char* x1[3] = {"one","two","three" };
const char* x2[2] = {"eins","zwei" };
// Variant 1
Menu m1(x1, 3);
m1.print();
// Variant 2
Menu2 m2(x2, 2);
m2.print();
}
Given a vector of objects, is there an elegant way to extract its member? I am currently just using a for loop but it would be nice if there is a way to do it. Example:
#include <vector>
struct Object {
int x;
float y;
};
int main() {
std::vector<Object> obj;
// Fill up obj
std::vector<int> all_x = obj.x; // Won't work obviously
}
With range-v3, it would simply be
std::vector<int> xs = objs | ranges::view::transform(&Object::x);
or just use the view:
auto xs = objs | ranges::view::transform(&Object::x);
Demo
As std::vector (or c++ in general) does not support covariant aggregation, there is no syntactically pretty way to do what you want.
If you really want to initialize all_x with x members of obj elements, then you can define a new iterator class, like that:
class getx_iter : public vector<Object>::iterator
{
public:
getx_iter(const vector<Object>::iterator &iter) : vector<Object>::iterator(iter) {}
int operator*() { return (*this)->x; }
};
Working code example
If you're okay with initializing an empty vector and then filling it, std::transform with a labmda is a clearer option (as #andars suggested).
You could also avoid extra initialization by using vector::reserve() and back_inserter:
xs.reserve(foos.size());
std::transform(foos.begin(), foos.end(), back_inserter(xs), [](Foo f){return f.x;});
Also notice that while x is a private member of Object and has no getters, it will be quite hard to extract it.
I can't think of a really good way.
One alternative would be to use std::transform with a lambda.
#include <vector>
#include <algorithm>
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
int main() {
std::vector<Foo> foos;
for (int i = 0; i<10; i++) {
foos.push_back(Foo(i));
}
std::vector<int> xs;
xs.resize(foos.size());
std::transform(foos.begin(), foos.end(), xs.begin(), [](Foo f){return f.x;});
}
Some template and macro magic, and it works:
#include <vector>
#include <algorithm>
using namespace std;
class Foo {
public:
Foo(int x_): x(x_) {}
int x;
};
#define GETFIELD(type, field) [](const type & obj){return obj.field;}
template<typename T,typename U, typename TMapper>
void MapVector(vector<T>& src, vector<U>& dst, TMapper mapper) {
for (const auto& it: src) {
dst.push_back(mapper(it));
}
}
#define MapVectorField(src, dst, field) MapVector(src, dst, GETFIELD(decltype(src)::value_type, field))
int main() {
vector<Foo> vFoo;
for (int i = 0; i < 10; i++) {
vFoo.push_back(Foo(i));
}
vector<int> vX;
MapVector(vFoo, vX, GETFIELD(Foo, x));
MapVectorField(vFoo, vX, x);
for (int i = 0; i < vX.size(); i++) {
printf("%d\n", vX[i]);
}
}
Of course, remember that it is not very good to name macro MapVectorField as it is function, or write using namespace std in production.
Here's another macro that's pretty easy to use. It does require the programmer to know that the internal loop variable name is "e", for element. If you keep that in mind, it will work for both fields or methods, and also for normal objects or pointers to objects.
The macro is simply:
#define map(vTarget, vSource, eField) \
for (auto e: vSource) { vTarget.push_back(eField); }
For example, suppose we have a class named Person which has a string name field and an int age field, and we want to extract just the names into a new vector. An example usage might then be:
map(names, people, e.name);
Note the "e" in the third parameter. This is required because the macro uses the variable "e" to iterator over the elements in the vector. So keep in mind which syntax you need to use. I believe these are the 4 cases:
e.field
e.method()
e->field
e->method()
Let's try them out. Here's a full example. Hey, if anyone has a more elegant join solution, I'm all ears.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
#define map(vTarget, vSource, eField) \
for (auto e: vSource) { vTarget.push_back(eField); }
class Person {
public:
string name;
int age;
public:
Person(string name, int age) {
this->name=name;
this->age=age;
}
string& getName() {return name;}
int getAge() {return age;}
};
string join(vector<string> vSource, const string separator) {
string buf;
bool first=true;
for (string e: vSource) {
if (first) {
first=false;
} else {
buf+=separator;
}
buf+=e;
}
return buf;
}
int main(int argc, char **argv) {
// using a normal Object
vector<Person> people;
vector<string> names;
people.push_back(Person("john", 27));
people.push_back(Person("jane", 26));
names.clear();
map(names, people, e.name);
cout << join(names, ",") << endl;
names.clear();
map(names, people, e.getName());
cout << join(names, ",") << endl;
// using a pointer to an object
vector<Person*> morePeople;
morePeople.push_back(new Person("bob", 27));
morePeople.push_back(new Person("amy", 26));
names.clear();
map(names, morePeople, e->name);
cout << join(names, ",") << endl;
names.clear();
map(names, morePeople, e->getName());
cout << join(names, ",") << endl;
}
Sample output:
john,jane
john,jane
bob,amy
bob,amy
Is there any way to dynamically (I think that's the right term) define an int array in a class, the size of which is a private member variable in that same class? For example:
class Scene()
{
//public member functions
private:
int max;
int xcoords[max];
}
I've searched through other answered questions on here, but I haven't learned how to use vectors in class yet, which is what most responses suggest. Ideally, in my constructor for the class, I'd be passed an int max, with which I then initialize the xcoord array to have a size of max with entries all -1.
If you want dynamic sizing for your member data, you almost certainly have to store it in the heap. Which means, something like this
class Foo{
int* data;
public:
Foo(int size){
data = new int[size];
}
~Foo(){
// remember to clean up
delete[] data;
}
}
This way, your constructor will allocate size for size ints in the heap memory when the class is created, and free it up when it is deleted.
The more official c++ way of writing the constructor is:
Foo(int size):
data(new int[size])
{
}
But in the end it will do the same thing.
Consider leaving memory management to standard libraries.
Instead of Arrays, use vectors.
#include <vector>
#include <iostream>
using std::vector;
using std::cout;
using std::endl;
class Scene
{
public:
vector<int> verticeData;
};
int LEGACY_FUNCTION(const int * data, int count)
{
for (int i = 0; i < count; ++i)
{
cout << " ";
cout << data[i];
cout << " ";
}
cout << endl;
return 0;
}
int main()
{
Scene myscene;
myscene.verticeData.emplace_back(3);
myscene.verticeData.emplace_back(4);
myscene.verticeData.emplace_back(5);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
myscene.verticeData.clear();
myscene.verticeData.emplace_back(1);
myscene.verticeData.emplace_back(7);
LEGACY_FUNCTION(myscene.verticeData.data(), myscene.verticeData.size());
return 0;
}