I try to make a function that can change the content of a specified char array
void change_array(char *target)
{
target="hi";
}
int main()
{
char *a[2];
change_array(a[1]);
cout<<*(a[1]);
}
But then the content of a[1] stays at 0x0(void)
First, your function has a copy of the pointer passed to it, so there is no effect seen on the caller side. If you want to modify the function argument, pass a reference:
void change_array(char*& target) { ... }
// ^
Second, you cannot/should not bind a non-const pointer to a string literal. Use const char* instead.
void change_array(const char*& target) { ... }
// ^^^^^ ^
int main()
{
const char* a[2];
change_array(a[1]);
cout<<*(a[1]);
}
When you pass an argument to a function, it's normally passed by value, meaning its value is copied. If you want to change it you have to pass it by reference. The same goes for pointers, if you want to change a pointer then you need to pass it by reference as well:
void change_array(const char*& target) { ... }
You need to pass it as a reference:
void change_array(char*&target)
{
target="hi";
}
Otherwise, you will just change the local copy of target, which won't make any difference to the value outside of the function.
Try this design instead:
std::string get_string()
{
return "hi";
}
int main()
{
std::string a[2];
a[1] = get_string();
std::cout<< a[1];
}
Salient points:
return by value
use std::string
Related
I'm a bit newbie to CPP and I don't know why the setValue() const works meanwhile it's a const.
Why the class allows modification from a const public
It seems really odd, there is no error on g++ -Wall or with MS Visual C++
Here is my code:
main.cpp
#include <iostream>
#include <cassert>
#include "DArray.h"
int main(void)
{
DArray darray(1);
darray.setValue(0, 42);
assert(darray.getValue(0) == 42);
darray.~DArray();
system("pause");
return 0;
}
DArray.h
class DArray
{
private:
int* tab;
public:
DArray();
DArray(unsigned int n);
~DArray();
int& getValue(unsigned int n) const;
void setValue(unsigned int n, int value) const;
};
DArray.cpp
#include "DArray.h"
DArray::DArray()
{
}
DArray::DArray(unsigned int n)
{
tab = new int[n];
}
DArray::~DArray()
{
delete[] tab;
tab = nullptr;
}
int& DArray::getValue(unsigned n) const
{
return tab[n];
}
void DArray::setValue(unsigned n, int value) const // HERE
{
tab[n] = value;
}
It is because you do not modify it. When you do:
int* tab
tab contains only an address. Then in
void DArray::setValue(unsigned n, int value) const // HERE
{
tab[n] = value;
}
You do not modify this address, you modify some memory after it. Thus you do not modify your class.
If instead, you used
std::vector<int> tab
You would have an error in setValue because you would modify an element of your class.
First of all, don't call explicitely the destructor of your class, this will be called when the variable goes out of scope automatically.
darray.~DArray();
What you are promising with const in the method is that the member variables will not be modified. The variable int* tab is a pointer to an int. With your setValue function you are not changing the address of the pointer (which is promised not to be changed by the final const in the signature of your method) but the int value pointed by it. This is fine.
However, if you change the pointer address, for example with tab = nullptr, you will see a compiler error like:
error: assignment of member 'DArray::tab' in read-only object
Why can I modify the class with a const function in C++11?
It is possible to modify mutable state of the object. It is technically also possible to modify the non-mutable state using const_cast, but it would be a bad idea to do so because if the object itself is const, then behaviour would be undefined.
That's however not what you do in this code.
why the setValue() const works meanwhile it's a const.
Because it doesn't modify any member of this. It modifies an array that is pointed by a pointer to non-const. Constness of a member function, or constness of the object is not transfer to an indirectly pointed object.
I don't understand why is crashing. I send a pointer to an array, alloc that array and then modify array. What is the problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void f(unsigned char *data) {
data = (unsigned char *)malloc(200);
}
int main() {
unsigned char *data = nullptr;
int i;
f(data);
memset(data, 0, 200);
}
You are passing data by value to f().
f() sets the value of its parameter.
Because the parameter was passed by value, this does absolutely nothing to the data variable in main(). f() leaks the allocated memory, and when it returns, main()'s data is still nullptr.
You should pass it by reference:
void f(unsigned char *&data)
Or, better yet, return it. f() doesn't need the parameter.
unsigned char *f() {
return (unsigned char *)malloc(200);
}
Change
void f(unsigned char *data) { // ....
to
void f(unsigned char *&data) { // ....
// ^
}
or
void f(unsigned char **data) {
*data = (unsigned char *)malloc(200);
}
and call
f(&data);
// ^
It's all about passing a reference to the data pointer to be initialized from within the function.
Your example passes data by value, and doesn't change the pointer outside of the function.
The call to f does not change the value of the variable data defined in main, as you seem to expect it to. It changes the value of the data defined in f, but because parameters are passed by value, that has no effect on the data defined in main.
I have got 2 functions:
char* odwroc(char* nap, int n)
char* male(char* nap, int n)
I have defined a pointer to that kind functions
typedef char*(*pointerToFunction )( char*, int );
then in used that definition in main:
pointerToFunction ptr1 = odwroc;
pointerToFunction ptr2 = male;
but now I have to create a function which as a first parameter gets array of that pointers to function and I am stuck. I don't know how to define array of pointers to function and how the modyfikuj parameter list should look like.
void modyfikuj(char* pointerToFunction *pointerArray, int length, char* nap2, int n){
}
Try this:
pointerToFunction mojefunkcje[] = { odwroc, male};
modyfikuj( mojefunkcje, ...); // pass the array fo modyfikuj()
void modyfikuj( pointerToFunction* funtab, ...)
{
funtab[0]( string, liczba); // call odwroc( string, liczba)
funtab[1]( string, liczba); // call male( string, liczba)
}
Even though the above answer make sense, use of containers such as std::vector will give you more control when passing an array of similar type such as a pointer to a function. Please try below code snippet.
#include "vector"
using namespace std;
typedef char*(*pointerToFunction )( char*, int );
typedef vector<pointerToFunction> FUNCTION_VECTOR;
bool modyfikuj( FUNCTION_VECTOR& vecFunctionVector )
{
// The below checking ensures the vector does contain at least one function pointer to be called.
if( vecFunctionVector.size() <= 0 )
{
return false;
}
// You can have any number of function pointers to be passed and get it executed, one by one.
FUNCTION_VECTOR::iterator itrFunction = vecFunctionVector.begin();
FUNCTION_VECTOR::const_iterator itrFunEnd = vecFunctionVector.end();
char* cszResult = 0;
for( ; itrFunEnd != itrFunction; ++itrFunction )
{
cszResult = 0;
// Here goes the function call!
cszResult = (*itrFunEnd)( "Hello", 1 );
// Check cszResult for any result.
}
return true;
}
char* odwroc(char* nap, int n); // You will define this function somewhere else.
char* male(char* nap, int n); // You will define this function somewhere else.
int main()
{
FUNCTION_VECTOR vecFunctions;
// You can push as many function pointers as you wish.
vecFunctions.push_back( odwroc );
vecFunctions.push_back( male );
modyfikuj( vecFunctions );
return 0;
}
I have to replace some char array code. So say I have a class that has an std::string member variable.
class foo
{
private:
std::string _sBar;
public:
const char* getBar() const { return _sBar.c_str(); }
};
existing code expects that const char*'s are returned in the string accessor functions, so I can't return a const std::string reference.
But isn't there some rule that when the stack unwinds that you can no longer trust the return value from the _sBar.c_str() ?
Yes, that's correct. Better if you ask the caller to supply a buffer with a fixed size say, the caller allocates as:
const int MAX = 1000; // choose some suitable value
char buff[MAX];
And the caller has a foo object,
foo a;
...
a.getBar(buff, MAX);
...
And you define getBar as:
void getBar(char *buffer, int size) const {
strncpy(buffer, _sBar.c_str(), size -1);
buffer[size -1] = 0;
}
you can make a copy of that string with new [ ] operator inside your member function, and it will be stored independently from the class object. In the class:
plublic:
const char* getBar() const {
char * str = new char[_sBar.length()+1];
strcpy(str, _sBar.c_str());
return str;}
In main:
foo object;
///some code
const char* bar = object.getBar();
///some code
delete [] bar;
Note it's good style to free the memory using delete [ ].
I am stuck in the following pointer problem:
Say you have a function:
void Function (unsigned char *ubPointer)
{
ubPointer++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
What I want is that the ++ is reflected in PointerX, without declaring it as a global variable.
Thank you very much.
In C++, pass your pointer by reference (and don't forget to specify a return type for your function):
void Function (unsigned char*& ubPointer)
// ^
{
ubPointer++;
}
This won't require any further change in the calling code. When returning from the function, the side-effects on ubPointer will be visible to the caller.
In C, you can achieve the equivalent result by passing a pointer to your pointer:
void Function (unsigned char** ubPointer)
// ^
{
(*ubPointer)++;
// ^^^^^^^^^^^^
}
This will require you to change the way you are calling your function:
int main()
{
unsigned char* p;
Function(&p);
// ^
}
Or, if you want to do it C-style
void Function (unsigned char **ubPointer)
{
(*ubPointer)++;
}
because
Function (unsigned char **ubPointer)
{
ubPointer++;
}
would be increasing the address pointed to.
void Function (unsigned char *ubPointer)
{
(*ubPointer)++;
}
int main (void)
{
unsigned char *PointerX;
Function( PointerX );
}
This is the correction