I'm new to using smart pointers, I'm trying to create the same but I have errors.
class data{
private:
int ID;
public:
void setID(int a){
ID=a;
}
int getID(){
return ID;
}};
int main(){
data d*;
d=new data[30];
for(int i=0;i<30;i++){
(p+i)->setID(i);
}}
I try with:
shared_ptr<data> sp( new data[30]);
for(int i=0;i<30;i++){
sp->setID(i)[i];
}
Error:invalid types 'void[int]' for array subscript|
shared_ptr<data> sp( new data[30]);
for(int i=0;i<30;i++){
(sp+i)->setID(i);
}
Error: No match for 'operator+' (operand types are 'std::shared_ptr' and 'int')|
how can i do the same?
The issue is you're trying to add i to sp, instead of to the pointer that is managed by sp. What you want to do is use get() to get the stored pointer first:
for (int i = 0; i < 30; i++) {
sp.get()[i].setID(i);
}
If you use C++17, there's also operator[] which you could use.
However, you've got another problem (and operator[] wouldn't work because of it). You are storing the result of new[] in a std::shared_ptr which expects to manage a pointer returned by new. Your construction of sp should actually be:
std::shared_ptr<data[]> sp(new data[30]);
Otherwise you'll get undefined behavior, because sp is going to call delete on the address returned by new data[30], whereas it needs to use delete[]. Here's a bunch more info about the constructors of std::shared_ptr.
Side notes:
Please provide a minimal, complete, and verifiable example for your questions.
Are you sure you need std::shared_ptr? Won't std::unique_ptr work? std::unique_ptr is basically as fast as a raw pointer, whereas std::shared_ptr is slower.
Related
I don't understand this part of the code below. I mean alloc_MY_CAR() returns some array and how does & work so that newTab->pFunFree = &free_MY_CAR sees this array which newTab->pDat returns?
I don't understand pointers well. I only know that & store address of variable and * is a pointer or a value of the variable.
Could anyone guide me on how to use it properly and how does it work? I'm a beginner, so don't be so hard on me.
Thanks in advance!
#pragma once
struct MY_CAR {
char *model;
int year;
};
void print_MY_CAR(void* pdata);
void free_MY_CAR(void *pdata);
MY_CAR* alloc_MY_CAR();
switch (typ) {
case 0:
newTab->pDat = alloc_MY_CAR();
newTab->pFunFree = &free_MY_CAR;
newTab->pFunPrint = &print_MY_CAR;
break;
}
MY_CAR* alloc_MY_CAR() {
MY_CAR* tab = (MY_CAR*)calloc(1, sizeof(MY_CAR));
if (!tab) {
exit(0);
}
else {
char model[125];
printf("Podaj model: ");
scanf("%s", model);
tab->model = (char*)calloc(strlen(model) + 1, sizeof(char));
strcpy(tab->model, model);
printf("Podaj rok: ");
scanf_s("%d", &tab->year);
}
return tab;
}
void free_MY_CAR(void *pdata) {
MY_CAR* car = (MY_CAR*)pdata;
if (!car || !car->model) return ;
free(car->model);
free(car);
}
Notice that the function free_MY_CAR has an argument of type void*,
a pointer to a "void" type
(which is a C idiom for a pointer to something without telling the type of the thing pointed to),
and the first thing it does is to reinterpret that pointer as a pointer to a MY_CAR.
So the function is probably intended to be called like this:
newTab->pFunFree(newTab->pDat);
That is, the way the functions "know" what pointer was returned by
alloc_MY_CAR() and stored in newTab->pDat
is that the programmer explicitly tells the functions what pointer
is stored in newTab->pDat.
The advantage of doing such things is that it allows some code to do some operation on a data structure without necessarily having to know what kind of data structure it will actually operate on when the program actually runs.
In the call to pFunFree above, newTab could have been initialized by the case 0 code shown in the question, but there could be another case
that initializes it with alloc_MY_JOB(), &free_MY_JOB, and &print_MY_JOB,
where the MY_JOB functions allocate/free/print a data structure that is quite different from the data structure used by
alloc_MY_CAR(), &free_MY_CAR, and &print_MY_CAR.
Then if you call
newTab->pFunPrint(newTab->pDat);
we might not be able to predict when we write the code whether it will print the contents of a data structure created by
alloc_MY_CAR() or by alloc_MY_JOB();
but we can predict that it will print the detailed information it has
about your car, or your job, or whatever was read from the data file and stored in newTab.
The property that we can make a function call that uses a data structure in a way appropriate to that data structure, without having to know when we write the code what the type of data structure will be, is called
polymorphism.
This is a cumbersome idiom and there are lots of ways to get it wrong.
One of the selling points of C++ is to enable people to write polymorphic objects more easily than this.
Just out of curiosity, I'm trying to understand how pointers to functions work in C.
In order to associate a function to a typedef, I've declared a pointer in it, and then I've stored the address of the desired function in there.
This is what I was able to achieve:
typedef struct
{
void (*get)(char*, int);
char string[10];
} password;
int main()
{
password userPassword;
userPassword.get = &hiddenStringInput;
userPassword.get(userPassword.string, 10);
return EXIT_SUCCESS;
}
While this does actually work perfectly, I'd like for "userPassword.get" to be a shortcut that when used calls the hiddenStringInput function and fills in the requested arguments (in this case, an array of characters and a integer).
Basically, since I'm always going to use userPassword.get in association with the arguments "userPassword.string" and "10", I'm trying to figure out a way to somehow store those parameters in the pointer that points to the hiddenString function. Is it even possible?
The way I see this usually done is by providing a "dispatch" function:
void get(password * pw) {
pw->get(pw->string, 10);
}
Then, after setting userPassword.get to your function, you call just:
get(userPassword);
Obviously this adds some boilerplate code when done for multiple functions. Allows to implement further funny "class like" things, though.
You can do this in Clang using the "Blocks" language extension. As commented, there have been attempts to standardize this (and it's not been received with hostility or anything), but they're moving slowly.
Translated to use Blocks, your example could look like this:
#include <stdlib.h>
#include <Block.h>
typedef void (^GetPw)(int); // notice how Block pointer types are used
typedef void (*GetPw_Impl)(char*, int); // the same way as function pointer types
typedef struct
{
GetPw get;
char string[10];
} password;
extern void hiddenStringInput(char*, int);
extern void setPw(char dst [static 10], char * src);
GetPw bindPw (GetPw_Impl get_impl, char * pw)
{
return Block_copy (^ (int key) {
get_impl (pw, key);
});
}
int main()
{
password userPassword;
setPw(userPassword.string, "secret");
userPassword.get = bindPw(hiddenStringInput, userPassword.string);
userPassword.get(10);
return EXIT_SUCCESS;
}
There are some subtleties to the way arrays are captured that might confuse this case; the example captures the password by normal pointer and assumes userPassword is responsible for ownership of it, separately from the block.
Since a block captures values, it needs to provide and release dynamic storage for the copies of the captured values that will be created when the block itself is copied out of the scope where it was created; this is done with the Block_copy and Block_release functions.
Block types (syntactically function pointers, but using ^ instead of *) are just pointers - there's no way to access the underlying block entity, just like basic C functions.
This is the Clang API - standardization would change this slightly, and will probably reduce the requirement for dynamic memory allocation to copy a block around (but the Clang API reflects how these are currently most commonly used).
So, I've just realized that I can write functions directly inside of structs
typedef struct
{
char string[10];
void get(void)
{
hiddenStringInput(string, 10);
return;
}
void set(const char* newPassword)
{
strcpy(string, newPassword);
return;
}
void show(void)
{
printf("%s", string);
return;
}
} password;
Now I can just call userPassword.get(), userPassword.show() and userPassword.set("something"), and what happens is exactly what the label says. Are there any reasons I shouldn't do this? This looks like it could come pretty handy.
EDIT: So this is only possible in C++. I didn't realize I'm using a C++ compiler and by attempting to do random stuff I came up with this solution. So this isn't really what I was looking for.
Hi I am working on a project where I access info from a file and then put it into an array of objects then manipulate the data in the object from a options from a menu. The problem I am currently having is that one of the options in the menu is to add a new element to the object. The project states that I must use an array of objects so I can't just use a vector the class that I'm putting the array into to resize it uses a temporary dynamic array for the object then deleting the original array.
Here's what the class looks like
class Info
{
private:
string name;
double money;
public:
Info(){
name="";
money=0;
}
void Setname(string n){
name=n;
}
void Setmoney(double m){
money=m;
}
string GetName()const{
return name;
}
double GetMoney()const{
return money;
}
};
now that was just a sample of the class the actual class has equations with it to alter the money variable but for the purpose of this question this is all that is needed. Now here is the function where I am having the problem
void Addinfo(Info in [], int & size){
string newname;
double newmoney;
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
delete []in;
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
in=temp;
size=size+1;
}
Now when I run the program everything runs fine until I try using this function in which the data in the arrays gets corrupts. Am I supposed to make the in Info variable a new dynamic array that can hold the can hold all the info then use another for loop to put the variables into the new dynamic array or I am supposed to do something else. Also remember that I must use arrays for this. Also when deleting a dynamic array am I supposed to make the former array equal to zero after deleting or is that something else?
When you have a function with a type valueName[] array parameter then you just pass the address of that array parameter to the function. The calling function has the ownership of that array. Besides the function signature you always have to consider a contract between the caller and the called function that defines the ownership of the data passed by pointer.
Your function AddInfo gets an array passed by pointer and the calling function expects that the data is available after the function call. So the function violates the contract when you delete []in.
Your function uses a parameter in as (local) variable when you assign a new value with in=temp;. That's legal. But you can't expect that the changed local variable has any effect to the caller. With the current function signature is possible to call the function in this way:
Info infos[5];
Addinfo(&info[3], 2);
Obviously it makes no sense to modify &info[3]. When your contract shall allow adding some data to the array you need a signature that allows changing a pointer. One example would be:
void Addinfo(Info*& in, int& size, string newname, double newmoney)
{
Info *temp= new Info[size+1];
for(int index=0; index<size;index++){
temp[index].Setname(in[index].GetName());
temp[index].Setmoney(in[index].GetMoney());
}
temp[size].Setname(newname);
temp[size].Setmoney(newmoney);
delete []in;
in = temp;
size=size+1;
}
void Addinfo(Info*& in, int& size)
{
string newname;
double newmoney;
// input data
cout<<"What name are you going to use?"<<endl;
cin>>newname;
cout<<"Now How much money do you have currently"<<endl;
cin>>newmoney;
// TODO: data validation.
// add data to array
Addinfo(in, size, newname, newmoney);
}
I have factored out the change of the array from the input. This allows a more simple testing of that function.
I'm about to debug someone else's code and I stumbled across a certain 'way' of handling with global arrays which I consider deeply bad, but the one who first used it swears to it.
I need to find arguments against it.
Here is the code written simplified (this is not the original code, just an abstracted version)
So my question: which arguments would you bring against (or maybe some code which brings down this method) this?
int test(int i, int v, int type, int** t)
{
static int *teeest;
int result = 0;
switch(type)
{
case (1):
{
int testarr[i];
teeest = testarr;
}
break;
case (2):
result = teeest[i];
break;
case (3):
teeest[i] = v;
break;
}
if (t != NULL)
{
*t = teeest;
}
return result;
}
int main()
{
int *te = (int*)1;
test(5, 0, 1, &te);
printf("%p\n", te);
int i=0;
for(;i<5;i++)
{
test(i, i, 3, NULL);
printf("Value: %d\n", test(i,0,2, NULL));
}
return 0;
}
local variables are dead after the block they declared in, so this code is undefined behavior. Like every accessing random address, it may work, but it also may not work.
Note that if you use malloc instead of int testarr[i], (and worry to free the previous array, and to initialize teeest), it will be correct. the problems of this code have nothing about static pointers.
This is really bad. Just because the pointer is static doesn't mean the data it points to will be around. For example, testarr disappears when the function exits and the returned pointer, if used, might cause dragons to appear.
It seems to me the big downfall of this style is that you are hiding the fact that you are accessing a locally declared array which is on the stack. Then you persist a pointer to your stack which will persist through calls, which will have different stacks each call.
Another thing I was thinking about is that you have hidden from the developer what the data structure is. Indexing an array is a normal operation. Indexing a pointer makes the developer acknowledge it is an array and not a more complex data type. This also adds confusion to bounds checking.
Another thing is, that all disadvantages of global variables apply directly. The code is not reentrant, and hard to make thread-safe (if that's a concern).
My project has both managed & unmanaged code. I wrote a class cIVR in managed code, while defining it in an unmanaged cpp file. The project has been working fine for some time.
Now I need to call a member function of one of objects in array 'arrChannels' from another function in the same file.
During array definition it's not allowing me to declare as static due to managed code, so I want to pass a reference to my array in a global pointer so I can access member function throughout the file.
I am using .Net 2008.
main() {
array<cIVR^>^ arrChannels = gcnew array<cIVR^>(num_devices); //MAXCHAN
for(int i=0; i< num_devices; i++) { //MAXCHAN
arrChannels[i] = gcnew cIVR();
}
I want some thing like ->
cIVR *ch; //global
ch = arrChannels; //last in above code
func2(int index) {
ch[index]->setNumber("123");
}
Aside from the 'having a global is generally not a good idea issue', the place to correctly initialise ch would be inside main() after you created the array.
I'd also strongly recommend using the correct prototypes for the functions that you're using, for example:
int main()
and
void func2(int index)