Страницы

Поиск по вопросам

Показаны сообщения с ярлыком параметры. Показать все сообщения
Показаны сообщения с ярлыком параметры. Показать все сообщения

вторник, 28 января 2020 г.

Java. Почему нельзя изменить ссылку на объект в методе?

#java #ссылки #объекты #теория #параметры


Мой педагог задал мне задание ответить на ряд вопросов. И два их них меня сильно
смущают. 


  
  Почему нельзя изменить ссылку на объект в методе?
  


Не могу понять смысл вопроса(((


  
  Как в Java передаются параметры в методы?
  


Я гуглил этот вопрос и понял что по всегда по значению но что точно это значит не понял.

Не могли бы вы мне помочь разобраться в этой ситуации.
    


Ответы

Ответ 1



Почему нельзя изменить ссылку на объект в методе? Потому что в метод передается не ссылка, а объект, который содержит копию ссылки. Как в Java передаются параметры в методы? Все аргументы (как примитивные типы, так и объекты) в Java передаются при вызове по значению. Тут сразу стоит оговориться, что объект по сути представляет ссылку, следовательно, при изменении объекта в методе, изменится и исходный объект. Подробнее можно почитать в «Подробное рассмотрение особенностей передачи аргументов» в полном руководстве по Java авторства Герберта Шилдта.

Ответ 2



Как намекнул Vlad from Moscow в комментарии к вопросу, вопрос довольно странный, и на мой взгляд он не вполне корректен -- либо ваш преподаватель не очень хорошо умеет выражать свои мысли, либо вы как-то слегка исказили его вопрос. Дело в том, что в методе менять ссылку вообще-то можно. Строго говоря, в Jave обычно говорят не о ссылках на объект, а о переменных (полях, аргументах) объектного типа. Но фактически значением таких переменных являются ссылки на объекты. Методы в качестве своих аргументов получают копии этих ссылок и могут делать с ними что хотят (т. е. присваивать им значения ссылок на другие объекты или null - "пустую ссылку"), что никак не отражается на значениях переменных, которые были переданы методу при его вызове. Так что вот такой код public class TestQQ { static void qq(String s) { System.out.println(s); s = "Что-то новое..."; // Это ссылка или не ссылка меняется ? System.out.println(s); } public static void main(String[] args) { String string = "Нельзя менять ссылки?"; qq(string); System.out.println(string); } } Создает новый объект класса String со значением "Нельзя менять ссылки?"; Присваивает ссылку на него переменной string; Вызывает метод qq() и передает ему копию переменной string (т. е. создает вторую ссылку на ту же строку "Нельзя менять ссылки?") Метод qq() выводит на консоль содержимое того объекта, ссылка на который содержится в его параметре - т. е. то же самое "нельзя?"; Метод qq() своему параметру s присваивает новое значение - ссылку на новую строку "Что-то новое...", -- вторая ссылка на "нельзя" исчезает, но исходная переменная string в главной программе при этом никак не меняется и по-прежнему содержит ссылку на то же самое изначальное "нельзя?"; Метод qq() печатает новую строку ("Что-то новое...") и возвращает управление в главную программу (метод main); Метод main() печатает содержимое объекта, который содержится (т. е. ссылка на который содержится) в переменной string - это по-прежнему изначальная строка "Нельзя менять ссылки?" Вывод будет такой:Нельзя менять ссылки? Что-то новое Нельзя менять ссылки? Но при этом надо отчетливо понимать, что хотя метод не может изменить значение объектной переменной, переданной ему в качестве параметра (т. е. ссылку на объект), он за милую душу может изменить сам объект! Например, в такой программе import java.util.ArrayList; public class TestQQQ { static void qqq(ArrayList list) { list.add("можно."); } public static void main(String[] args) { ArrayList strings = new ArrayList(); strings.add("А объекты менять...?"); qqq(strings); System.out.println(strings); } } метод qqq() добавляет в список, ссылку на который он получил, новую строку "можно.", и в результате мы получаем на выходе вот что: [А объекты менять...?, можно.]

Ответ 3



Почему нельзя изменить ссылку на объект в методе? При передаче объекта в метод происходит просто копирование ссылки на него (Никаких копий объекта не создаётся при передачи!). И уже с помощью неё вы общаетесь с исходным объектом. Отсюда должно быть понятно, почему при перезаписывании в эту ссылку нового объекта старый не меняется. Простой пример для разъяснения: List list1 = new ArrayList<>(); //Создаём объект и кладём в ссылку List list2 = list1; //Просто копируем ссылку list2.add(new Object); //Через копию ссылки мы меняем исходный объект в list1 list2 = new ArrayList<>(); //Хоть мы и переписали в ссылку новый объект, //исходный никуда не делся, он всё также лежит в list1. Как в Java передаются параметры в методы? Примитивы по значению, объекты - как я описал выше (не знаю как правильно называется этот способ). Update: спасибо @Roman, правильное название способа передачи объектов в метод - вызов по соиспользованию (call by sharing)

суббота, 11 января 2020 г.

Как экранировать SQL запрос, чтобы избежать SQL injections?

#python #sql #postgresql #параметры


Каким образом можно экранировать SQL запрос, чтобы избежать SQL injection?

def getStackArea(screen_area):
    db = postgresql.open(db_conf.connectionString())
    data = db.query("select stack_area from screen_coordinates where screen_area
= " + screen_area + " and active = 1")
    return data[0]['stack_area']

    


Ответы

Ответ 1



Пример: conn = psycopg2.connect(dsn) cur = conn.cursor() q = "select stack_area from screen_coordinates where screen_area = ? and active = ?" cur.execute(sql, (screen_area,1)) row = cur.fetchone() stack_area = row[0] или используя py-postgresql: q = "select stack_area from screen_coordinates where screen_area = $1 and active = $2" row = db.query.first(sql, (screen_area,1)) ... PS похоже параметризация в py-postgresql реализована не в полном объеме, как это описано в PEP-249

понедельник, 6 января 2020 г.

c# сделать функцию параметром функции

#c_sharp #aspnet #функции #делегаты #параметры


Есть множество функций типа flipImageV. До и после кода в этих функциях должны быть
одинаковые строки кода. Что бы в каждой функции типа flipImageV их не писать, хочу
сделать одну, куда буду передавать нужную функцию на выполнение...

Вот универсальная функция, куда передаю выбранную функцию типа flipImageV:

protected void editImage(delegate func) {
        currentImage.ImageUrl = @"..\images\img0.jpg";
        func();
        photo.Save(@"~\" + imagePath);
    }


Функция типа flipImageV:

protected void flipImageV(object sender, EventArgs e) {
        photo.FlipVertical();
    }


Использование того шаблона: 

editImage(flipImageV);


или

protected void flipImageV(object sender, EventArgs e) {
        editImage(photo.FlipVertical());
    }


Что должно быть вместо delegate func? Как это лучше сделать?
    


Ответы

Ответ 1



Используйте просто Action: protected void editImage(Action func) { currentImage.ImageUrl = @"..\images\img0.jpg"; func(); photo.Save(@"~\" + imagePath); } Вызывать как-то так: editImage(() => photo.FlipVertical()); Если вам нужно непременно передавать внутрь функцию наподобие flipImageV, которая получает два игнорируемых аргумента, можно так: editImage(() => flipImageV(null, EventArgs.Empty));

Что значит: “virtual void funcC( double = 0.0 );”?

#cpp #функции #параметры


Добрый день.
Случайно наткнулся на функцию у которой непонятно что записано в параметрах:


  virtual void funcC( double = 0.0 )


Если бы было имя переменной, то было бы понятно что это за параметр или если бы эта
штука не компилировалась бы, то это была бы опечатка) Так нет же, все компилируется
и работает. Что вот это такое, в чем его смысл: double = 0.0 ?
    


Ответы

Ответ 1



Значение по умолчанию. Если вы вызовите ее как Obj.funcC() - это будет воспринято как Obj.funcC(0.0). Словом, читайте, что такое значения аргументов функций по умолчанию - например, тут. Имени переменной нет - потому что она может быть просто зарезервирована или не нужна. Например, в наследнике она может понадобиться. А в базовом классе она не нужна. struct Base { virtual void out(double = 0.0) { cout << "Base::out\n"; } }; struct Derived: public Base { virtual void out(double x) { cout << "Drived::out " << x << "\n"; } }; int main(int argc, const char * argv[]) { Base * b = new Derived; b->out(); // Тут вызовется out() из Derived со значением 0.0 b->out(3); // Тут - со значением 3.0 } Имени аргумента в Base не нужно - он не используется, и нужен только для обеспечения сигнатуры. Если ввести какое-то имя - компилятор справедливо заметит, что имя есть, но не используется. Тут - он промолчит.

воскресенье, 5 января 2020 г.

В чём смысл std::forward при передаче параметров?

#cpp #шаблоны_с++ #ссылки #параметры


В чём разница между следующими двумя способами передачи параметров?

template  smth(Args &&...args) : base(args...) {}




template  smth(Args &&...args) : base(std::forward(args)...) {}

    


Ответы

Ответ 1



Предположим, что конструктор base принимает move-only параметр по значению: struct base { base(std::unique_ptr value); }; В таком случае первый вариант не скомпилируется: template smth(Args &&...args) : base(args...) {} попытка сделать копию ^^^^ Тут можно написать std::move и это будет работать: template smth(Args &&...args) : base(std::move(args)...) {} Однако в случае если у base два конструктора, один из которых перемещает значение, а другой принимает ссылку: struct base { base(std::unique_ptr&& value); base(std::unique_ptr& value); }; И если мы хотим чтобы smth передавал в base именно те типы аргументов, с которыми его вызвали, то std::move нам не подойдет - он всегда будет превращать аргумент в r-value ссылку. Для этого есть std::forward, который сохраняет оригинальный тип аргумента: struct smth : base { template smth(Args &&...args) : base(std::forward(args)...) {} }; std::unique_ptr p; smth s1(p); // OK, будет вызван base(std::unique_ptr&); smth s2(st::move(p)); // OK, будет вызван base(std::unique_ptr&&); Примечание: std::forward(t) работает только с "универсальнами ссылками", т.е. когда T - это параметр шаблона функции (конструктора), а t - аргумент этой функции с типом T&& (это специальное исключение в языке, такой тип T&& не является r-value ссылкой, а заставляет T повторять тип того, что передали в функцию).

понедельник, 30 декабря 2019 г.

Передача параметра по ссылке с++

#cpp #функции #ссылки #параметры


Как передать функции параметр по ссылке со значением по умолчанию?

void func(int &i)

void func2(set &s)


и при этом иметь возможность вызывать эти функции без аргументов, чтобы переменной
i присваивалось значение по умолчанию, а для s вызывался конструктор, чтобы использовать
множество set в теле функции.
    


Ответы

Ответ 1



Если вы хотите использовать аргумент по умолчанию по ссылке, то этот аргумент должен быть не временным объектом и уже где-то быть определенным на момент вызова функции. Передача аргумента по неконстантной ссылке предполагает, что этот исходный аргумент будет в функции изменен. Вы не можете передавать по неконстантной ссылке временные объекты. Поэтому, исходя из условий, указанных в вашем вопросе, скорей всего у вас должны быть две перегруженные функции. Одна функция принимает аргумент по lvalue-ссылке с конкретно заданным объектом. Вторая функция оибл принимает временный объект по rvalue-сслке, оибо вместо него использует значение по умолчанию. Например, #include void func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; } void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; } int main() { int i = 0; std::cout << "Before func( i ) i = " << i << std::endl; func( i ); std::cout << "After func( i ) i = " << i << std::endl; std::cout << std::endl; i = 0; std::cout << "Before func() i = " << i << std::endl; func(); std::cout << "After func() i = " << i << std::endl; return 0; } Вывод программы на консоль: Before func( i ) i = 0 Inside func( int & ) i = 1 After func( i ) i = 1 Before func() i = 0 Insde func( int && ) i = 1 After func() i = 0 В этой программе, когда в качестве аргумента передается lvalue, то используется первая функция void func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; } и она меняет в своем теле исходный аргумент. Когда же аргумент не указывается, или когда указывается rvalue, то есть некоторый временный объект, как, например, func(); // используется аргумент по умолчанию int(), который равен 0 или func( 10 ); // используется временный объект - целочисленный литерал - 10 то используется вторая функция void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; } Если же вы не собираетесь изменять исходный аргумент, то достаточно объявить одну функцию с параметром в виду константной ссылки. Например, void func( const int &i = int() );

Ответ 2



Ну, первый случай несложен - если вы хотите иметь возможность использовать значение по умолчанию, то используйте const int& - void f(const int& i = 5) { cout << i << endl; } Без const, как вы понимаете, вам не удастся передать значение - ведь что тогда вы собираетесь менять, передавая число? :) А вот так - можно: int j = 5; void f(int& i = j) { cout << i << endl; } int main(int argc, const char * argv[]) { int q = 4; f(); f(q); } Соответственно, то же и с set& - как вы себе представляете для s вызывался конструктор, чтобы использовать множество set в теле функции Т.е. вы хотите создавать новый set? Тогда где он должен быть создан? Как локальная переменная, как глобальная, как переменная в вызывающей функции? Так что по умолчанию для ссылки надо указывать имеющийся объект. Другое просто не имеет никакого смысла. В конце концов, ссылка - это просто адрес, ждя которого гарантируется наличие корректного объекта. "По-моему, так" (с) Пух

Ответ 3



Если вам нужна именно неконстантная ссылка, то сделать в такой ситуации можно что-то вроде void func2(set &s = some_function()) где some_function это set &some_function() { ... } некая функция, которая отвечает за создание этих экземпляров std::set в некоем хранилище. Отдельно придется подумать об обеспечении некоей политики их последующего уничтожения, когда они станут ненужными. Как это будет делаться - вопрос отдельный и элегантных решений тут навскидку не видно. Оптимальное решение может зависеть от конкретной специфики вашей задачи, но сама идея неявного создания (потенциально долгоживущих) объектов через параметр по-умолчанию - сомнительна.

суббота, 30 ноября 2019 г.

Передача указателей в функцию C++

#cpp #функции #указатели #ссылки #параметры


Вопрос по C++. При передаче обычной переменной в функцию создается, как я понимаю,
её копия. А что происходит, когда мы передаем указатель? Создается ли копия указателя
или нет?
    


Ответы

Ответ 1



Если у вас объявлена функция с параметром, как, например, void f( T t ); где T - это некоторый тип, и эта функция вызывается с некоторым выражением, переданным ей в качестве аргумента, как f( exp ); то инициализацию параметра можно представить следующим образом void f( /* T t */ ) { T t = exp; //... то есть параметр - это локальная переменная функции, которая инициализируется тем выражением, которое передано функции в качестве аргумента. Следовательно изменения параметра никак не сказываются на исходном аргументе, ели только тип T не является ссылочным типом. Сравните две функции void f( int *p ) { p = new int( 10 ); } void g( int * &p ) { p = new int( 10 ); } и их вызов int main() { int *p = nullptr; f( p ); if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl; g( p ); if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl; delete p; } В этом примере при вызове функции f имеет место утечка памяти, так как память, распределенная в функции, не освобождается. Параметр функции - локальная переменная p - при выходе из функции удаляется, и тем самым адрес выделенной динамически памяти будет утерян. У функции g параметр имеет ссылочный тип, то есть эта ссылка на переданный функции аргумент. Поэтому функция имеет дело с исходным аргументом и меняет его в своем теле, присваивая ему адрес выделенной памяти. Также можно передать указатель на указатель, если требуется изменить исходный указатель в функции. Например, void h( int **p ) { *p = new int( 10 ); } Вызов функции будет выглядеть как h( &p );

Ответ 2



Создается. Внутри функции вы можете присвоить указателю другое значение и это не повлияет на внешнюю переменную. #include void foo(int* p) { p = nullptr; std::cout << "inside: " << p << std::endl; } int main() { int v; int* p = &v; std::cout << "before: " << p << std::endl; foo(p); std::cout << "after: " << p << std::endl; } before: 0x7ffd4a1eba94 inside: 0 after: 0x7ffd4a1eba94 Рабочий пример.

пятница, 12 июля 2019 г.

Передача двумерного массива по ссылке С++

Есть двумерный массив чисел. Int mass[15][20] Нужно передать его в функцию так, чтобы изменение его в функции отражалось в main. После попыток разобраться поняла, что нужно как-то передавать по ссылке, но не могу сообразить как.


Ответ

Передавайте. Только скобочки не забудьте:
#include
void f(int (& mass)[15][20]) { mass[1][1] = 42; }
int main() { int mass[15][20] = { 0 }; f(mass); std::cout << mass[1][1] << std::endl; return 0; }

вторник, 26 марта 2019 г.

Java. Почему нельзя изменить ссылку на объект в методе?

Мой педагог задал мне задание ответить на ряд вопросов. И два их них меня сильно смущают.
Почему нельзя изменить ссылку на объект в методе?
Не могу понять смысл вопроса(((
Как в Java передаются параметры в методы?
Я гуглил этот вопрос и понял что по всегда по значению но что точно это значит не понял.
Не могли бы вы мне помочь разобраться в этой ситуации.


Ответ

Почему нельзя изменить ссылку на объект в методе?
Потому что в метод передается не ссылка, а объект, который содержит копию ссылки
Как в Java передаются параметры в методы?
Все аргументы (как примитивные типы, так и объекты) в Java передаются при вызове по значению. Тут сразу стоит оговориться, что объект по сути представляет ссылку, следовательно, при изменении объекта в методе, изменится и исходный объект.

Подробнее можно почитать в «Подробное рассмотрение особенностей передачи аргументов» в полном руководстве по Java авторства Герберта Шилдта.

среда, 13 февраля 2019 г.

c# сделать функцию параметром функции

Есть множество функций типа flipImageV. До и после кода в этих функциях должны быть одинаковые строки кода. Что бы в каждой функции типа flipImageV их не писать, хочу сделать одну, куда буду передавать нужную функцию на выполнение...
Вот универсальная функция, куда передаю выбранную функцию типа flipImageV:
protected void editImage(delegate func) { currentImage.ImageUrl = @"..\images\img0.jpg"; func(); photo.Save(@"~\" + imagePath); }
Функция типа flipImageV:
protected void flipImageV(object sender, EventArgs e) { photo.FlipVertical(); }
Использование того шаблона:
editImage(flipImageV);
или
protected void flipImageV(object sender, EventArgs e) { editImage(photo.FlipVertical()); }
Что должно быть вместо delegate func? Как это лучше сделать?


Ответ

Используйте просто Action
protected void editImage(Action func) { currentImage.ImageUrl = @"..\images\img0.jpg"; func(); photo.Save(@"~\" + imagePath); }
Вызывать как-то так:
editImage(() => photo.FlipVertical());

Если вам нужно непременно передавать внутрь функцию наподобие flipImageV, которая получает два игнорируемых аргумента, можно так:
editImage(() => flipImageV(null, EventArgs.Empty));

четверг, 13 декабря 2018 г.

Передача параметра по ссылке с++

Как передать функции параметр по ссылке со значением по умолчанию?
void func(int &i)
void func2(set &s)
и при этом иметь возможность вызывать эти функции без аргументов, чтобы переменной i присваивалось значение по умолчанию, а для s вызывался конструктор, чтобы использовать множество set в теле функции.


Ответ

Если вы хотите использовать аргумент по умолчанию по ссылке, то этот аргумент должен быть не временным объектом и уже где-то быть определенным на момент вызова функции.
Передача аргумента по неконстантной ссылке предполагает, что этот исходный аргумент будет в функции изменен. Вы не можете передавать по неконстантной ссылке временные объекты.
Поэтому, исходя из условий, указанных в вашем вопросе, скорей всего у вас должны быть две перегруженные функции. Одна функция принимает аргумент по lvalue-ссылке с конкретно заданным объектом. Вторая функция оибл принимает временный объект по rvalue-сслке, оибо вместо него использует значение по умолчанию.
Например,
#include
void func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; }
void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; }
int main() { int i = 0;
std::cout << "Before func( i ) i = " << i << std::endl;
func( i );
std::cout << "After func( i ) i = " << i << std::endl;
std::cout << std::endl;
i = 0;
std::cout << "Before func() i = " << i << std::endl;
func();
std::cout << "After func() i = " << i << std::endl;
return 0; }
Вывод программы на консоль:
Before func( i ) i = 0 Inside func( int & ) i = 1 After func( i ) i = 1
Before func() i = 0 Insde func( int && ) i = 1 After func() i = 0
В этой программе, когда в качестве аргумента передается lvalue, то используется первая функция
void func( int &i ) { ++i; std::cout << "Inside func( int & ) i = " << i << std::endl; }
и она меняет в своем теле исходный аргумент.
Когда же аргумент не указывается, или когда указывается rvalue, то есть некоторый временный объект, как, например,
func(); // используется аргумент по умолчанию int(), который равен 0
или
func( 10 ); // используется временный объект - целочисленный литерал - 10
то используется вторая функция
void func( int &&i = int() ) { ++i; std::cout << "Insde func( int && ) i = " << i << std::endl; }
Если же вы не собираетесь изменять исходный аргумент, то достаточно объявить одну функцию с параметром в виду константной ссылки. Например,
void func( const int &i = int() );

среда, 10 октября 2018 г.

Передача указателей в функцию C++

Вопрос по C++. При передаче обычной переменной в функцию создается, как я понимаю, её копия. А что происходит, когда мы передаем указатель? Создается ли копия указателя или нет?


Ответ

Если у вас объявлена функция с параметром, как, например,
void f( T t );
где T - это некоторый тип, и эта функция вызывается с некоторым выражением, переданным ей в качестве аргумента, как
f( exp );
то инициализацию параметра можно представить следующим образом
void f( /* T t */ ) { T t = exp; //...
то есть параметр - это локальная переменная функции, которая инициализируется тем выражением, которое передано функции в качестве аргумента. Следовательно изменения параметра никак не сказываются на исходном аргументе, ели только тип T не является ссылочным типом.
Сравните две функции
void f( int *p ) { p = new int( 10 ); }
void g( int * &p ) { p = new int( 10 ); }
и их вызов
int main() { int *p = nullptr;
f( p );
if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl;
g( p );
if ( p == nullptr ) std::cout << "p is equal to nullptr" << std::endl; else std::cout << "p is not equal to nullptr" << std::endl;
delete p; }
В этом примере при вызове функции f имеет место утечка памяти, так как память, распределенная в функции, не освобождается. Параметр функции - локальная переменная p - при выходе из функции удаляется, и тем самым адрес выделенной динамически памяти будет утерян.
У функции g параметр имеет ссылочный тип, то есть эта ссылка на переданный функции аргумент. Поэтому функция имеет дело с исходным аргументом и меняет его в своем теле, присваивая ему адрес выделенной памяти.
Также можно передать указатель на указатель, если требуется изменить исходный указатель в функции. Например,
void h( int **p ) { *p = new int( 10 ); }
Вызов функции будет выглядеть как
h( &p );