Опе­ра­ция за­пя­тая в C++

Как ни стран­но, про­грам­ми­сты ред­ко уде­ля­ют вни­ма­ние изу­че­нию и ис­поль­зо­ва­нию опе­ра­ции за­пя­тая (comma operator) в язы­ке C++. Да­вай­те посмот­рим, что это та­кое.

Пре­жде все­го, сле­ду­ет знать, что не вся­кая за­пя­тая в тек­сте ва­шей про­грам­мы яв­ля­етcя опе­ра­ци­ей. Пе­ре­чис­лим за­пя­тые, ко­то­рые яв­ля­ют­ся не опе­ра­ци­я­ми, а раз­де­ли­те­ля­ми:

  • За­пя­тые, раз­де­ляю­щие ар­гу­мен­ты мак­ро­под­ста­но­вок. При­мер:
    #define MIN(a, b) (((a) < (b)) ? (a) : (b))
  • За­пя­тые, раз­де­ляю­щие ар­гу­мен­ты шаб­ло­нов. При­мер:
    template<class A, class B> class C;
  • За­пя­тые, раз­де­ляю­щие ар­гу­мен­ты функ­ции (при её опре­де­ле­нии, опи­са­нии, и вы­зо­ве);
  • За­пя­тые, раз­де­ляю­щие пе­ре­мен­ные при опи­са­нии не­сколь­ких пе­ре­мен­ных:
    int a, *b, c;
  • За­пя­тые, раз­де­ляю­щие вы­зо­вы кон­ст­рук­то­ров внут­рен­них объ­ек­тов. При­мер:
    class C{int x; float y; public: C(void): x(9), y(2.5) { ; } };
  • За­пя­тые, раз­де­ляю­щие эле­мен­ты ини­циа­ли­за­то­ров мас­си­вов и ст­рук­тур:
    int a[] = {1, 2, 3};

Осталь­ные за­пя­тые яв­ля­ют­ся опе­ра­ци­я­ми. Опе­ра­ция за­пя­тая име­ет са­мый низ­кий при­о­ри­тет сре­ди всех опе­ра­ций язы­ка C++. У этой опе­ра­ции есть 2 опе­ран­да (ле­вый и пра­вый). Вна­ча­ле вы­чис­ля­ет­ся ле­вый опе­ранд, за­тем пра­вый, а в ка­че­стве ре­зуль­та­та воз­вра­ща­ет­ся пра­вый опе­ранд. Три­ви­аль­ный при­мер:

int a = (1 + 2, 3 + 4); //В результате a == 3+4 == 7. Заключёно в
                        //  скобки, так как иначе запятая была бы
                        //  воспринята, как разделитель переменных

Ес­ли пра­вый опе­ранд опе­ра­ции за­пя­тая яв­ля­ет­ся ле­вос­то­рон­ним вы­ра­же­ни­ем (име­ет ад­рес и не яв­ля­ет­ся кон­стан­той), то ре­зуль­та­том то­же яв­ля­ет­ся ле­вос­то­рон­нее вы­ра­же­ние. В этом слу­чае ре­зуль­та­ту мож­но при­сваи­вать зна­че­ние или вы­чис­лять ад­рес:

int a = 1, b = 2;
(a, b) = 3; //В результате a==1, b==3

По­боч­ные эф­фек­ты

Пусть вы­ра­же­ние «по­боч­ный эф­фект» вас не пу­га­ет, — это дей­ствие, со­вер­шен­но осо­знан­но за­про­грам­ми­ро­ван­ное раз­ра­бот­чи­ком про­грам­мы. «По­боч­ный» — не обя­за­тель­но «пло­хой»; сло­во при­об­ре­ло от­ри­ца­тель­ный от­те­нок из-за ле­карств, ко­то­рые обыч­но име­ют один те­ра­пев­ти­че­ский эф­фект и мно­го по­боч­ных.

За­чем же вы­чис­лять зна­че­ния обо­их опе­ран­дов, ес­ли зна­че­ние ле­во­го всё рав­но не ис­поль­зу­ет­ся? Де­ло в том, что в про­цес­се вы­чис­ле­ния опе­ран­да мо­гут быть про­из­ве­де­ны до­пол­ни­тель­ные дей­ствия, на­зы­вае­мые по­боч­ны­ми эф­фек­та­ми. На­при­мер, мо­гут быть мо­дифи­ци­ро­ва­ны ка­кие-ли­бо пе­ре­мен­ные в про­грам­ме, или вы­пол­не­ны не­ко­то­рые внеш­ние дей­ствия (вы­вод на экран, за­пись на диск).

Опе­ра­ция за­пя­тая пред­на­зна­че­на для то­го, что­бы впи­хи­вать дей­ствия с по­боч­ны­ми эф­фек­та­ми в те ме­ста про­грам­мы, где ком­пи­ля­тор ожи­да­ет один опе­ра­тор. Как вы уви­ди­те да­лее, от этой воз­мож­но­сти язы­ка про­грам­ми­ро­ва­ния нет ни­ка­кой поль­зы — по­нят­ность про­грам­мы сни­жа­ет­ся, а до­пол­ни­тель­ные дей­ствия мож­но вы­пол­нить и без за­пя­тых.

При­тя­ну­тые за уши при­ме­ры ис­поль­зо­ва­ния

Рас­смот­рим не­сколь­ко при­ме­ров. Пусть у нас опи­са­ны 4 функ­ции и 3 пе­ре­мен­ных:

//Определяем функции нахождения минимума для разного числа аргументов:
int min(int a) { return a; }
//Запятая разделяет аргументы функции. Это не операция:
int min(int a, int b) { return a < b ? a : b; }
int min(int a, int b, int c) { return min(min(a, b), c); }
//Вывод аргумента на экран (побочный эффект) и возврат значения аргумента:
int out(int x) { cout << x; return x; }

int a, b, c; //Это не операция запятая. Это перечисление переменных

По­иг­ра­ем­ся с опе­ра­ци­ей за­пя­тая. Пре­жде все­го, про­ве­рим её при­о­ри­тет:

a = (1, 2, 3); //В итоге a == 3, так как запятая возвращает
               //  правый аргумент

b = 1, 2, 3; //Операция запятая имеет самый низкий приоритет,
             //  поэтому строка эквивалентна (b = 1), 2, 3;
             //  В итоге b == 1, а числа 2 и 3 не используются.

Об­ра­ти­те вни­ма­ние на то, как скоб­ки из­ме­ни­ли смысл вы­ра­же­ния. В сле­дую­щем при­ме­ре из­ме­не­ние смыс­ла ещё бо­лее не­ожи­дан­но, так как ка­жет­ся, что ((вы­ра­же­ние)) и (вы­ра­же­ние) — это од­но и то же:

a = min(1, 2, 3); //Запятые разделяют аргументы функции. В итоге a == 1

b = min((1, 2, 3)); //Операции запятая. В итоге b = min(3) == 3.

Частая ошиб­ка «пас­ка­ли­стов» — на­пи­са­ние че­рез за­пя­тую ин­дек­сов мно­го­мер­но­го мас­си­ва. До­пу­стим, у нас есть два дву­мер­ных мас­си­ва, каж­дый из ко­то­рый сде­лан, как мас­сив ука­за­те­лей на од­но­мер­ные мас­си­вы:

int const width = 10, height = 10;
int **a = new int*[height];
int **b = new int*[height];
for(int y=0; y<height; ++y)
{
    a[y] = new int[width];
    b[y] = new int[width];
    for(int x=0; x<width; ++x)
    {
        a[y][x] = 1; //Массив a заполнен единицами
        b[y][x] = 0; //Массив b заполнен нулями
    }
}

А те­перь мы хо­тим ско­пи­ро­вать мас­сив a в b по­эле­мент­но, но слу­чай­но на­пи­са­ли ин­дек­сы мас­си­ва че­рез за­пя­тую:

for(int y=0; y<height; ++y)
{
    for(int x=0; x<width; ++x)
        b[y,x] = a[y,x]; //Какой ужас!
}

Ком­пи­ля­тор в этом слу­чае не вы­даст ни оши­бок, ни пре­ду­пре­жде­ний. Ин­те­рес­но то, что при пр­осмот­ре со­дер­жи­мо­го мас­си­ва b он бу­дет со­сто­ять из еди­ниц, как мы и ожи­да­ем. Вот толь­ко при мо­дифи­ка­ции мас­си­ва b «сам со­бой» те­перь бу­дет мо­дифи­ци­ро­вать­ся и мас­сив a, что мо­жет при­ве­сти к стран­ным глю­кам в дру­гих ме­стах про­грам­мы:

b[0][0] = 3;
cout << a[0][0] <<endl; //Выведет 3

Для тех, кто не по­нял, от­че­го так про­ис­хо­дит, по­яс­ню. В вы­ра­же­нии b[y,x] = a[y,x]; у нас на­пи­са­ны опе­ра­ции за­пя­тая, ко­то­рые «иг­но­ри­ру­ют» ле­вый ар­гу­мент. По­это­му вы­ра­же­ние эк­ви­ва­лент­но вы­ра­же­нию b[x] = a[x];. То есть ука­за­те­ли на стро́ки мас­си­ва b мы за­ме­ня­ем ука­за­те­ля­ми на стро́ки мас­си­ва a; по­сле это­го стро­ка­ми обо­их мас­си­вов яв­ля­ют­ся од­ни и те же бу­фе­ры па­мя­ти. Не­за­мет­но­сти ошиб­ки по­спо­соб­ство­ва­ло так­же то, что вы­со­та мас­си­ва сов­па­да­ет с ши­ри­ной (в вы­ра­же­нии b[x] = a[x] мы ин­дек­си­ру­ем мас­сив, имею­щий раз­мер height, ин­дек­сом, ме­няю­щим­ся от 0 до width-1).

За­пя­тая как точ­ка сле­до­ва­ния

Важ­но, что опе­ра­ция за­пя­тая опре­де­ля­ет в про­грам­ме точ­ку сле­до­ва­ния. Это озна­ча­ет, что сна­ча­ла пол­но­стью вы­чис­ля­ет­ся вы­ра­же­ние сле­ва от за­пя­той, а за­тем — вы­ра­же­ние спра­ва. Для срав­не­ния, опе­ра­ция сло­же­ния точ­ку сле­до­ва­ния не опре­де­ля­ет, по­это­му:

a = out(1), out(2), out(3); //В итоге a == 1, а на экран выведется 123, так как
                            //  аргументы операции запятая вычисляются слева-
                            //  направо (значит, в этом же порядке происходят
                            //  вызовы функций)

a = ( out(1), out(2), out(3) ); //В результате a == 3, на экране по прежнему 123

b = out(1) + out(2) + out(3); //На экране выведутся цифры 123 в неопределённом
                              //  порядке. (123 или 321 или ещё как-нибудь)

c = min( out(1), out(2), out(3) ); //Аргументы функции. Порядок не определён

В мо­ём слу­чае (Visual C++ 2010, Release) про­грам­ма вы­ве­ла 123123123321 при вы­пол­не­нии преды­ду­ще­го ко­да.

Ес­ли вам ин­те­рес­но, то в про­грам­мах на C++ есть ещё не­сколь­ко мест, в ко­то­рых опре­де­ле­ны точ­ки сле­до­ва­ния: это ло­ги­че­ские опе­ра­ции &&, || и ?:, раз­де­ли­тель опе­ра­то­ров ;, точ­ки вхо­да и вы­хо­да из функ­ций.

Кро­ме то­го, точ­ки сле­до­ва­ния опре­де­ле­ны на ме­сте за­пя­тых, раз­де­ляю­щих пе­ре­мен­ные при их опи­са­нии. По­это­му мо­же­те сме­ло пи­сать int x = 1, y = x + 1; не бо­ясь, что y = x + 1 вы­чис­лит­ся до то­го, как ик­су при­сво­ит­ся еди­ни­ца. Будь­те вни­ма­тель­ны, не спу­тай­те эти за­пя­тые с те­ми, что раз­де­ля­ют ар­гу­мен­ты функ­ции, — там то­чек сле­до­ва­ния нет.

За­пя­тая в опе­ра­то­рах цик­лов

Те­перь рас­смот­рим воз­мож­но­сти при­ме­не­ния за­пя­той в опе­ра­то­ре цик­ла for. Вна­ча­ле при­мер, где за­пя­тая раз­де­ля­ет объ­яв­ле­ния пе­ре­мен­ных (не яв­ля­ет­ся опе­ра­ци­ей):

for(int x=0, y=3; x<y; ++x) out(x); //Выведет 012

Ес­ли в пер­вом вы­ра­же­нии цик­ла for опи­сы­ва­ют­ся пе­ре­мен­ные (как в при­ве­дён­ном при­ме­ре), то они вы­нуж­де­ны иметь оди­на­ко­вый тип. Кро­ме вы­бо­ра ини­циа­ли­зи­рую­щих зна­че­ний пе­ре­мен­ных ни­ка­кой сво­бо­ды у нас нет. Един­ствен­ный спо­соб впих­нуть в это вы­ра­же­ние ка­кое-ли­бо до­пол­ни­тель­ное дей­ствие — это до­ба­вить вы­зов функ­ции и/или опе­ра­цию за­пя­тая спра­ва от опе­ра­ции ини­циа­ли­за­ции:

for(int x=out(0), y=3; x<y; ++x) out(x); //Выведет 0012
for(int x=( out(9), 0 ), y=3; x<y; ++x) out(x); //Выведет 9012

По­след­ний при­мер — со­вер­шен­но бес­по­лез­ная вещь, ибо out(9) мож­но на­пи­сать и пе­ред цик­лом. Ещё ма­ло­по­лез­ные при­ме­не­ния:

for(int x=0, y=9; x<y; ++x, --y) out(x), out(y); //Выведет 0918273645

За­пя­тая поз­во­ли­ла нам мо­дифи­ци­ро­вать два ин­дек­са в опе­ра­то­ре цик­ла, а так­же обой­тись без фи­гур­ных ско­бок при вы­во­де двух чи­сел. По­след­ний при­мер мож­но пе­ре­пи­сать так:

for(int x=0, y=9; x<y; ) { out(x); out(y); ++x; --y; }

Воз­ни­ка­ет впе­чат­ле­ние, что поль­за есть толь­ко от раз­де­ли­тель­ных за­пя­тых, а за­пя­тая-опе­ра­ция лишь услож­ня­ет по­ни­ма­ние про­грам­мы, не да­вая ни­ка­ких но­вых воз­мож­но­стей про­грам­ми­сту. За­чем эта опе­ра­ция во­об­ще бы­ла вве­де­на в C и C++?

Мне всё же уда­лось най­ти два по­лез­ных при­ме­не­ния опе­ра­ции за­пя­тая. Пер­вое — это вы­пол­не­ние до­пол­ни­тель­ных дей­ствий в услов­ных вы­ра­же­ни­ях цик­лов for и while. Вто­рое — это пе­ре­груз­ка опе­ра­ции за­пя­тая для то­го, что­бы она слу­жи­ла со­вер­шен­но иным це­лям.

Вна­ча­ле рас­смот­рим ис­поль­зо­ва­ние в услов­ных вы­ра­же­ни­ях цик­лов. До­пу­стим, пе­ред про­вер­кой усло­вия цик­ла тре­бу­ет­ся вы­пол­нить не­ко­то­рые дей­ствия (на­при­мер, вы­чис­лить зна­че­ние функ­ции), и вы­чис­лен­ное зна­че­ние тре­бу­ет­ся нам внут­ри цик­ла. То­гда есть смысл на­пи­сать та­кой код:

//Перебираем значения x. Условие продолжения работы цикла --
//  положительность некоторой функции f(x)
for(float x=0.0, y; y=f(x), y>0.0; x+=0.1) cout << x << ", " << y << endl;

Ана­ло­гич­но для цик­ла while:

float x = 0.0, y;
while(y=f(x), y>0.0) { cout << x << ", " << y << endl; x+=0.1; }

Об­ра­ти­те вни­ма­ние, что опи­са­ние пе­ре­мен­ных мы мо­жем по­ме­стить пе­ред цик­лом, на­ра­щи­ва­ние зна­че­ний этих пе­ре­мен­ных мо­жем по­ме­стить в кон­це те­ла цик­ла, а вот вы­зов функ­ции f(x) мы не мо­жем ни­ку­да пе­ре­не­сти, ина­че нам при­дёт­ся на­пи­сать его два­жды: пе­ред цик­лом и в кон­це те­ла цик­ла.

При­ве­дён­ные при­ме­ры мож­но реа­ли­зо­вать и без за­пя­тых, ис­поль­зуя воз­вра­ща­е­мое зна­че­ние опе­ра­ции при­сваи­ва­ния:

for(float x=0.0, y; (y=f(x)) > 0.0; x+=0.1) cout << x << ", " << y << endl;

float x = 0.0, y;
while( (y=f(x)) > 0.0 ) { cout << x << ", " << y << endl; x+=0.1; }

Но мы смог­ли обой­тись без за­пя­той лишь по­то­му, что за­да­ча про­стая. Бы­ло бы у нас, на­при­мер, две функ­ции вме­сто од­ной — и за­пя­тая бы очень при­го­ди­лась.

Твор­че­ское при­ме­не­ние опе­ра­ции за­пя­тая опи­сан­ным вы­ше спо­со­бом мож­но най­ти в сле­дую­щей про­грам­ме, вы­чис­ляю­щей 800 де­ся­тич­ных цифр чис­ла \pi (по­дроб­но­сти здесь):

#include<stdio.h>
int a=10000,b,c=2800,d,e,f[2801],g;int main(){for(;b-c;)f[b++]=a/5;for(;d=0,g=c*2;
c-=14,printf("%.4d",e+d/a),e=d%a)for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);}

Пе­ре­груз­ка опе­ра­ции за­пя­тая

Мы по­дроб­но изу­чи­ли ис­поль­зо­ва­ние опе­ра­ции за­пя­тая, и по­ка об­на­ру­жи­ли лишь од­но по­лез­ное при­ме­не­ние. К сча­стью, язык про­грам­ми­ро­ва­ния C++ поз­во­ля­ет пе­ре­гру­зить опе­ра­цию за­пя­тая для то­го, что­бы она слу­жи­ла ка­ким угод­но це­лям. Син­так­сис пе­ре­груз­ки оче­ви­ден:

возвр_тип operator,(тип1 арг1, тип2 арг2) { ... }

Сле­ду­ет знать о том, что точ­ка сле­до­ва­ния, опре­де­лён­ная на ме­сте опе­ра­ции за­пя­тая, ис­че­за­ет при пе­ре­груз­ке этой опе­ра­ции. Этот эф­фект вы­зван тем, что за­пя­тая в слу­чае пе­ре­груз­ки пре­вра­ща­ет­ся в обыч­ный вы­зов функ­ции, а по­ря­док вы­чис­ле­ния ар­гу­мен­тов при вы­зо­ве функ­ции не опре­де­лён.

Опе­ра­ция мо­жет быть шаб­лон­ной, а ар­гу­мен­ты мо­гут быть пе­ре­да­ны по ссыл­кам. В об­щем, про­сто­ра для твор­че­ства мно­го (этот про­стор огра­ни­чен толь­ко тем, что хо­тя бы один из ар­гу­мен­тов пе­ре­опре­де­ля­е­мой опе­ра­ции дол­жен быть поль­зо­ватель­ским клас­сом).

Но и тут за­пя­тая по­ка­зы­ва­ет свой сквер­ный ха­рак­тер. Не­осто­рож­но пе­ре­опре­де­лив эту опе­ра­цию для ка­ких-ли­бо ши­ро­ко ис­поль­зуе­мых в про­грам­ме ти­пов дан­ных, мы мо­жем на­ру­шить про­грам­му в со­вер­шен­но не­ожи­дан­ных ме­стах (в том чис­ле мо­гут на­чать не­вер­но ра­бо­тать стан­дарт­ные кон­тей­не­ры).

Рас­смот­рим до­воль­но ча­стое при­ме­не­ние пе­ре­гру­жен­ной опе­ра­ции за­пя­тая — ком­пакт­ную за­пись ини­циа­ли­за­ции кон­тей­не­ров. На­при­мер, вме­сто та­ко­го ко­да:

vector<int> c;
c.push_back(10); c.push_back(20); c.push_back(30); c.push_back(40);

по­яв­ля­ет­ся воз­мож­ность пи­сать та­кой код:

vector<int> c;
c << 10, 20, 30, 40;

До­бить­ся опи­сан­ной функ­цио­наль­но­сти мож­но дву­мя спо­со­ба­ми:

  1. Сде­лать так, что­бы обе опе­ра­ции (за­пя­тая и <<) до­бав­ля­ли эле­мент (пра­вый ар­гу­мент) в кон­тей­нер (ле­вый ар­гу­мент), и воз­вра­ща­ли ссыл­ку на кон­тей­нер. По при­чи­не, опи­сан­ной вы­ше, это пло­хой спо­соб, так как опе­ра­ция за­пя­тая нач­нёт сра­ба­ты­вать в не­ожи­дан­ных ме­стах про­грам­мы. Да и смыс­ла не бу­дет в за­пя­той, ибо мож­но бу­дет пи­сать так: c << 10 << 20 << 30 << 40;
  2. Сде­лать так, что­бы опе­ра­ция << воз­вра­ща­ла объ­ект спе­ци­аль­но­го клас­са, и опре­де­лить за­пя­тую имен­но для это­го клас­са.

Реа­ли­зу­ем вто­рой ва­ри­ант. Пре­жде все­го, со­зда­дим шаб­лон­ный класс CommaInserter, ко­то­рый со­дер­жит ссыл­ку на кон­тей­нер. При кон­струи­ро­ва­нии объ­ект это­го клас­са бу­дет за­по­ми­нать ссыл­ку на кон­тей­нер и до­бав­лять в не­го пер­вый эле­мент. Кро­ме то­го, CommaInserter бу­дет иметь соб­ствен­ную опе­ра­цию за­пя­тая, ко­то­рая бу­дет до­бав­лять оче­ред­ной эле­мент:

template<class C> class CommaInserter
{
private: C &container;
public:
    template<class V> inline CommaInserter(C &container, V const &value):
        container(container) { container.insert(container.end(), value); }
    template<class V> inline CommaInserter<C> operator,(V const &value)
        { container.insert(container.end(), value); return *this; }
};

Те­перь до­опре­де­лим опе­ра­ции << и < для то­го, что­бы они со­зда­ва­ли эк­зем­пляр CommaInserter. Вто­рая опе­ра­ция от­ли­ча­ет­ся от пер­вой тем, что вна­ча­ле очи­ща­ет кон­тей­нер:

template<class C, class V>
    inline CommaInserter<C> operator<<(C &container, V const &value)
{ //Начинает добавление элементов в контейнер, создавая CommaInserter
    return CommaInserter<C>(container, value);
}

template<class C, class V>
    inline CommaInserter<C> operator<(C &container, V const &value)
{ //Очищает контейнер и начинает добавление элементов
    container.clear();
    return CommaInserter<C>(container, value);
}

Пред­став­лен­ные опе­ра­ции << и < для ком­пи­ля­то­ра име­ют ми­ни­маль­ный при­о­ри­тет (при­о­ри­тет не в смыс­ле по­ряд­ка вы­пол­не­ния опе­ра­ций, а в смыс­ле то­го, ка­кая имен­но реа­ли­за­ция опе­ра­ции бу­дет вы­бра­на ком­пи­ля­то­ром), так как эти опе­ра­ции шаб­лон­ные, и все ар­гу­мен­ты у них шаб­лон­ные. По­это­му не сто­ит пе­ре­жи­вать, что опе­ра­ции сра­бо­та­ют в «лиш­них» ме­стах: ес­ли уж про­грам­мист пи­шет << при­ме­ни­тель­но к ка­ко­му-ли­бо объ­ек­ту, то про­грам­мист яв­но хо­чет вы­пол­нить с объ­ек­том ка­кое-ли­бо дей­ствие (а не про­сто раз­де­лить два дей­ствия, как в слу­чае с за­пя­той).

По­иг­ра­ем­ся с на­ши­ми но­вы­ми опе­ра­ци­я­ми:

//Вектор из стандартной библиотеки (#include <vector>)
vector<int> v; //Пустой вектор
v << 1, 2, 3;  //Добавляем элементы: [1, 2, 3]
v << 2, 3, 4;  //Добавляем ещё элементы: [1, 2, 3, 2, 3, 4]
v < 3, 4, 5;   //Очищаем вектор и добавляем элементы: [3, 4, 5]

//Множество из стандартной библиотеки (#include <set>)
set<int> s;
s << 3, 2, 1, 3; //Добавляем элементы в множество. Множество всегда
                 //  отсортировано, и не содержит повторений,
                 //  поэтому s = {1, 2, 3}
s << 2, 5; //Ещё пара элементов: s = {1, 2, 3, 5}
s < 1, 2;  //Очищаем и добавляем: s = {1, 2}

Хо­чет­ся ве­рить, что пред­став­лен­ные опе­ра­ции бу­дут ра­бо­тать со все­ми кон­тей­не­ра­ми из стан­дарт­ной биб­лио­те­ки и с боль­шин­ством поль­зо­ватель­ских кон­тей­не­ров, под­дер­жи­ваю­щих ите­ра­то­ры.

За­клю­че­ние

Мы уви­де­ли, что C++ — не столь про­стой язык, как ка­жет­ся. Да­же ба­наль­ные за­пя­тые в нём яв­ля­ют­ся слож­ны­ми и мно­го­гран­ны­ми сущ­но­стя­ми (мо­гут яв­лять­ся раз­де­ли­те­ля­ми или опе­ра­ци­я­ми, мо­гут опре­де­лять ли­бо не опре­де­лять точ­ку сле­до­ва­ния, мо­гут быть пе­ре­гру­же­ны...). Ес­ли вы зна­е­те ещё о ка­кой-ли­бо осо­бен­но­сти за­пя­тых, не от­ра­жён­ной в этом ру­ко­вод­стве, про­шу пи­сать в ком­мен­та­ри­ях.

87 отзывов на запись «Опе­ра­ция за­пя­тая в C++»

Весь пост не про­чи­тал, но по­хо­же для for не ука­зан та­кой слу­чай, где все-та­ки за­пя­тая удоб­на:
for ( int i = 0, j = 0; i < i_max; ++i, j = i * i) {
    if ( condition ) {
        continue;
        // после continue будет выполнено ++i, j = i * i,
        // иначе пришлось бы писать j = i * i для каждого continue;
    }
    // код, который не нужен при condition,
    // но j = i * i все равно должно выполнятся;
}
В ре­зуль­та­те при ис­поль­зо­ва­нии continue вы­пол­ня­ет­ся код, ко­то­рый мож­но по­том ме­нять при не­об­хо­ди­мо­сти толь­ко в од­ном ме­сте, а не пе­ред каж­дым continue. Т. е. все-та­ки удоб­ство есть, а вы пи­ши­те "Воз­ни­ка­ет впе­чат­ле­ние, что поль­за есть толь­ко от раз­де­ли­тель­ных за­пя­тых, а за­пя­тая-опе­ра­ция лишь услож­ня­ет по­ни­ма­ние про­грам­мы, не да­вая ни­ка­ких но­вых воз­мож­но­стей про­грам­ми­сту".
Спа­си­бо, хо­ро­ший при­мер.
Мож­но бы­ло вы­пол­нить j = i * i до if ( condition ) с тем же ре­зуль­та­том.
А во­об­ще — по­зна­ва­тель­но, спа­си­бо.
А ну­жен ли здесь continue?
for ( int i = 0, j = 0; i &lt; i_max; ++i, j = i * i) {
    if ( !condition ) {
        // код, который не нужен при condition
    }
}
По идее ни­чем не ху­же. Опе­ра­ции ++i и j = i * i мож­но без ущер­ба вы­не­сти в ко­нец цик­ла (хоть я бы не стал это­го де­лать), и они бу­дут ра­бо­тать так же. .
Вот веч­но так — ка­кой-нить при­ду­рок вче­ра про­чи­тал ка­ко­го-нить Рих­те­ра, а зав­тра уже стро­чит гов­но­ста­тьи в ин­тер­не­те. >>> Пусть вы­ра­же­ние «по­боч­ный эф­фект» вас не пу­га­ет, — это дей­ствие, со­вер­шен­но осо­знан­но за­про­грам­ми­ро­ван­ное раз­ра­бот­чи­ком про­грам­мы. «По­боч­ный» — не обя­за­тель­но «пло­хой»; Ты ещё ска­жи вез­де void * пе­ре­да­вать, а в нуж­ном ме­сте пи­сать что-то вро­де *((double *)m). Ну а че­го та­ко­го? Это же бу­дет со­вер­шен­но осо­знан­но за­про­грам­ми­ро­ва­но! А то что от­ла­дить та­кое гов­но слож­нее так ко­го это ебёт, да? А то что разо­брать­ся в по­боч­ных эф­фек­тах тво­их за­пя­тых дру­гим лю­дям по­том при­дёт­ся это ни­хе­ра страш­но­го, да? Им ведь так хо­чет­ся из-за та­ко­го му­да­ка в оче­ред­ной раз до­ста­вать стан­дарт или K&R и пе­ре­чи­ты­вать их, тра­тя своё ра­бо­чее или лич­ное вре­мя, про­сто что­бы разо­брать­ся как про­грам­ма бу­дет ве­сти се­бя, при том, что всё это гов­но мож­но бы­ло рас­пи­хать по от­дель­ным опе­ра­то­рам, и ни­ка­ких про­блем бы не воз­ник­ло! >>>Сле­ду­ет знать о том, что точ­ка сле­до­ва­ния, оп­ре­де­лён­ная на ме­сте опе­ра­ции за­пя­тая, ис­че­за­ет при пе­ре­груз­ке этой опе­ра­ции. Этот эф­фект вы­зван тем, что за­пя­тая в слу­чае пе­ре­груз­ки пре­вра­ща­ет­ся в обыч­ный вы­зов функ­ции, а по­ря­док вы­чис­ле­ния ар­гу­мен­тов при вы­зо­ве функ­ции не оп­ре­де­лён. Зае­бись! У нор­маль­но­го че­ло­ве­ка в этом ме­сте долж­но в баш­ке щёлк­нуть, что нихуя хо­ро­ше­го из та­ких ве­сё­лых ве­щей в прин­ци­пе не мо­жет по­лу­чить­ся. Эта ста­тья — перл упо­ро­то­го кре­ти­на. Нор­маль­ные про­грам­ми­сты стре­мят­ся из­бе­гать по­боч­ных эф­фек­тов там где они мо­гут и в осо­бен­но­сти там где эти по­боч­ные эф­фек­ты не да­ют ни­че­го. При­мер:
int c;
while((c = getc(stdio)) != EOF)
{
    /* do something */
}
Это свое­об­раз­ная иди­о­ма в язы­ке Си. В по­доб­ном кон­тек­сте ис­поль­зо­ва­ние по­боч­но­го эф­фек­та оправ­да­но — это удоб­но, про­грам­ма ве­дёт се­бя пред­ска­зу­е­мо и «вы­лез­ти» где-ни­будь этот по­боч­ный эф­фект не мо­жет. Дру­гое де­ло опе­ра­ция за­пя­тая. На­хе­ра она во­об­ще нуж­на кро­ме по­рож­де­ния по­боч­ных эф­фек­тов? Нор­маль­ные про­грам­ми­сты дав­но взя­ли се­бе за пра­ви­ло — од­но дей­ствие в про­грам­ме од­на строч­ка ко­да. За­пя­тая поз­во­ля­ет за­пи­хать в од­ну строч­ку сколь­ко угод­но дей­ствий и при том ещё и сде­лать всё это дерь­мо од­ним опе­ра­то­ром! Где во­об­ще это мо­жет при­го­дит­ся? Это как из «Вой­ны и мир» все точ­ки, про­бе­лы и за­пя­тые убрать, сде­лать все бук­вы строч­ны­ми и за­ста­вить по­том ко­го-то это чи­тать. Я бы на ме­сте кол­лег та­ких гов­но­пи­са­те­лей еб­ло за та­кое бил. Го­луб в «Ве­рёв­ке до­ста­точ­ной длин­ны» во­об­ще со­ве­ту­ет не ис­поль­зо­вать за­пя­тую. Поль­зы от неё ни­ка­кой по­чти все­гда. Лиш­няя строч­ка-две в про­грам­ме ни­ко­му не ме­ша­ет, ско­рость вы­пол­не­ния про­грам­мы за­пя­ты­ми не по­вы­сишь. Ко­неч­но ино­гда код на­пи­сан­ный с за­пя­ты­ми вы­гля­дит изящ­нее, но эта про­сто­та толь­ко ка­жу­щая­ся, и ко­гда вы ко­гда-ни­будь столк­нё­тесь с труд­но­уло­ви­мой ошиб­кой, по­рож­дён­ной по­боч­ным эф­фек­том за­пя­той вы пой­мё­те на­сколь­ко до­ро­го об­хо­дит­ся эта ка­жу­щая­ся «изящ­ность». Кста­те, как пра­ви­ло та­кая ошиб­ка об­на­ру­жи­ва­ет­ся прак­ти­че­ски мгно­вен­но, по­сле то­го как вы раз­би­ва­е­те за­пя­тую на два нор­маль­ных опе­ра­то­ра. На­по­сле­док при­ве­ду ци­та­ту Waldi Ravens: «Про­грам­ми­ро­ва­ние на С по­хо­же на быст­рые тан­цы на толь­ко что от­по­ли­ро­ван­ном по­лу лю­дей с ост­ры­ми брит­ва­ми в ру­ках.» Нуж­но быть не очень ум­ным че­ло­ве­ком что­бы на­ме­рен­но «на­хе­ра­чи­вать» по­тен­ци­аль­ных опас­но­стей се­бе же са­мо­му в та­ких не слиш­ком «безопас­ных» для «тан­цев» язы­ках как С или С++.
Я с ва­шим ком­мен­та­ри­ем аб­со­лют­но со­гла­сен, ес­ли не брать в рас­чёт фра­зу «эта ста­тья — перл упо­ро­то­го кре­ти­на». (Бук­валь­но вче­ра я по­лу­чил справ­ку в нар­ко­ло­ги­че­ском дис­пан­се­ре, что я не упо­ро­тый, и справ­ку в пси­хо­нев­ро­ло­ги­че­ском дис­пан­се­ре, что я не кре­тин. Так что на этот счёт я спо­ко­ен.) Те­перь ка­са­тель­но ва­шей агрес­сии. Пред­ставь­те се­бе, я то­же по­ни­маю, что код нуж­но не толь­ко на­пи­сать, но и до­ку­мен­ти­ро­вать, и под­дер­жи­вать, и от­ла­жи­вать, и по­мо­гать кол­ле­гам этим ко­дом поль­зо­вать­ся. Я что, где-то аги­ти­ро­вал за ис­поль­зо­ва­ние опе­ра­ции за­пя­тая? Ней­траль­ный стиль из­ло­же­ния дан­ной ста­тьи не озна­ча­ет то­го, что я счи­таю за­пя­тую чем-то хо­ро­шим. Это дан­ность. Вы­ступ­лю лишь в за­щи­ту пе­ре­груз­ки за­пя­той для ини­циа­ли­за­ции кон­тей­не­ров: в биб­лио­те­ках Eigen и OpenCV та­ким спо­со­бом мож­но за­пол­нять мат­ри­цы. Учи­ты­вая, что эти биб­лио­те­ки до­ста­точ­но ши­ро­ко рас­про­стра­не­ны, и на­пи­са­ны лю­дь­ми от­нюдь не глу­пы­ми, я счёл важ­ным упо­мя­нуть это при­ме­не­ние за­пя­той, как впол­не удоб­ное и оправ­дан­ное. Вот веч­но так — ка­кой-нить при­ду­рок вче­ра про­чи­тал ка­ко­го-нить Рих­те­ра, а зав­тра уже стро­чит гов­но­ста­тьи в ин­тер­не­те. Мне это яв­ле­ние то­же не нра­вит­ся.
Не по­ни­маю ва­ше­го не­га­ти­ва. Че­ло­век по­дроб­но и по­нят­но рас­ска­зал о не слиш­ком ис­поль­зу­е­мом опе­ра­то­ре. У K&R, кста­ти, на­пи­са­но го­раз­до мень­ше. То, что зло­упо­треб­ле­ние за­пя­той мо­жет сде­лать про­грам­му бо­лее за­пу­тан­ной, от­нюдь не озна­ча­ет, что вы с ней ни­ко­гда не столк­нё­тесь. Мне один раз на со­бе­се­до­ва­нии по­па­лась за­дач­ка на за­пя­тую (на со­бе­се­до­ва­ни­ях во­об­ще очень лю­бят та­кие ве­щи).
Но есть у та­ких на­деж­ных бро­не­кон­ст­рук­ций и боль­шой не­до­ста­ток — они се­рьез­ная пре­гра­да не толь­ко для зло­умыш­лен­ни­ков, но и для по­жар­ных. При на­гре­ве зам­ки мо­гут за­бло­ки­ро­вать­ся.
Зам­ки для ме­тал­ли­че­ских две­рей тра­ди­ци­он­но до­ро­же и слож­нее в уста­нов­ке и за­ме­не. Бы­ва­ют да­же та­кие, на ко­то­рых за­ме­на зам­ка в прин­ци­пе не преду­смот­ре­на про­из­во­ди­те­лем.
На­деж­ная ме­тал­ли­че­ская дверь, ко­неч­но, по­вы­ша­ет безопас­ность Ва­ше­го жи­ли­ща, но ни­как не га­ран­ти­ру­ет пол­ной не­при­кос­но­вен­но­сти. Взлом­щи­ки поль­зу­ют­ся раз­лич­ны­ми хит­ры­ми улов­ка­ми и при­бо­ра­ми (на­при­мер, уг­ло­вой шли­фо­валь­ной ма­ши­ной). Воз­дей­ствию та­ких ин­стру­мен­тов под­вер­жен бой бе­то­на бой кир­пи­ча лю­бой ме­талл, но на­деж­ная дверь мак­си­маль­но за­дер­жит пре­ступ­ни­ка и смо­жет его от­влечь. По­это­му мы со­ве­ту­ем не пре­не­бре­гать креп­кой и ка­че­ствен­ной ме­тал­ли­че­ской две­рью на вхо­де сво­ей квар­ти­ры или до­ма.
Et ce n est qu un debut. http://lenitsky.com/semki-klipa-obnimi-menya-zavershenyi-backstage/ La telemedecine a en effet sa place en geriatrie.
propranolol cost
generic for strattera
atenolol
Hello!
По­зна­ком­люсь:
с Пар­нем
в воз­расте 26-30 лет
Цель зна­ком­ства:
Брак, со­зда­ние се­мьи
Ин­те­ре­сы
Fitness
Ти­паж
Те­ло­сло­же­ние:
Обыч­ное
Рост:
168 см
Вес:
70 кг
Во­ло­сы на го­ло­ве:
Тем­ные
Цвет глаз:
Ка­рие
Ре­ли­гия:
Хри­сти­ан­ство
Со­цио­ни­че­ский тип:
Есе­нин (ли­рик)
Зна­ние язы­ков:
Рус­ский
Тип внеш­но­сти:
Кав­каз­ская
Про­фес­сия:
До­мо­хо­зяй­ка не ра­бо­таю в де­кре­те
Ма­те­ри­аль­ное по­ло­же­ние:
Не­по­сто­ян­ные за­ра­бот­ки
Про­жи­ва­ние:
Жи­ву с ро­ди­те­ля­ми
Де­ти:
Есть, жи­вем вме­сте
Де­ти парт­нё­ра:
Не про­тив де­тей парт­не­ра
Cов­ме­ст­ные де­ти:
По­ка не знаю, как по­лу­чит­ся
Сек­су­аль­ные пред­по­чте­ния
loveawake
Как ча­сто Вы хо­те­ли бы за­ни­мать­ся сек­сом?
Для ме­ня секс не очень ва­жен
Раз­мер гру­ди
Сред­няя
Ме­ня воз­буж­да­ет:
Ин­тим­ная об­ста­нов­ка
Normally I do not read post on blogs, but I wish to say that this writeup very compelled me to try and do it! Your writing style has been surprised me. Thanks, quite great article.
brand viagra
buy eurax
cheap vermox
erythromycin 500 mg
please check out my pics
buy baclofen
wh0cd816070
wh0cd342518
wh0cd127638
wh0cd775574
wh0cd49942 Cialis Pills
fantastic put up, very informative. I’m wondering why the opposite specialists of this sector do not understand this. You should proceed your writing. I am confident, you’ve a
great readers’ base already!
Hurrah, that’s what I was searching for, what a stuff! present here at this blog, thanks admin of this web site.
I’m really loving the theme/design of your website. Do you ever run into any internet
browser compatibility problems? A couple of my blog readers have complained about my blog not
working correctly in Explorer but looks great
in Opera. Do you have any tips to help fix this problem?
Hello!
I must thank you for the efforts you’ve put in writing this site. I’m hoping to check out the same high-grade content by you in the future as well.
In truth, your creative writing abilities has encouraged me to get my very own site now
I blog often and I really appreciate your information. This article
has truly peaked my interest. I’m going to bookmark your site and keep checking for new information about once
per week. I opted in for your Feed as well.
Hey There. I found your blog using msn. This is a really well
written article. I will make sure to bookmark it and return to read more of your useful information. Thanks for the post. I’ll definitely return.
What you typed was very logical. But, consider this,
what if you were to create a awesome post title?
I ain’t suggesting your content isn’t good, but what if you
added something that grabbed people’s attention? I mean Опе­ра­ция
за­пя­тая в C++ | Image Processing is kinda boring. You should peek at Yahoo’s home page and watch how they create post headlines to get people to open the
links. You might try adding a video or a pic or two to
get people excited about what you’ve got to say. In my opinion, it could bring your
website a little bit more interesting.
We’re a group of volunteers and opening a new scheme in our community.
Your site offered us with valuable info to work on. You have done
an impressive job and our entire community will be thankful to you.
I am now not positive the place you are getting your
information, however great topic. I needs to spend some time finding
out much more or understanding more. Thanks for fantastic info I used to be looking
for this information for my mission.
Good web site you have got here.. It’s hard to find quality writing
like yours these days. I really appreciate individuals like
you! Take care!!
Hello!
Oh my goodness! Amazing article dude! Thanks, However I am encountering problems with your
RSS. I don’t know why I am unable to subscribe to it.
Is there anybody else having the same RSS issues?
Anyone who knows the answer can you kindly respond?
Thanx!!
I’ve been surfing online more than 4 hours today, yet I never found any interesting
article like yours. It’s pretty worth enough for me.
In my view, if all web owners and bloggers made good content as you did,
the web will be much more useful than ever before.
Do you mind if I quote a few of your posts as long as I provide
credit and sources back to your webpage? My blog is in the very same niche as yours and my
users would certainly benefit from some of the information you present here.
Please let me know if this ok with you. Thank
you!
Way cool! Some very valid points! I appreciate you penning this post plus the rest of the website is
also really good.
I would like to thank you for the efforts you have put in writing this
blog. I am hoping to see the same high-grade content from you in the future as well.
In fact, your creative writing abilities has
inspired me to get my own site now
What’s up, this weekend is pleasant in favor of me, for the reason that this
moment i am reading this wonderful informative post here at my house.
Hi, i think that i noticed you visited my website so i got here to return the prefer?.I’m attempting to in finding things to improve my web site!I
guess its adequate to use some of your concepts!!
I’m not certain where you are getting your information, but good topic. I needs to spend some time finding out much more or working out more. Thanks for excellent information I was searching for this info for my mission.
Hi, yes this article is really pleasant and
I have learned lot of things from it about blogging. thanks.
With havin so much content and articles do you ever run into any problems
of plagorism or copyright violation? My site has a lot of unique content I’ve either
created myself or outsourced but it appears a lot of it
is popping it up all over the internet without my agreement. Do you know any solutions to help protect against content from being stolen?
I’d certainly appreciate it.
Hello!
Woah! I’m really digging the template/theme of this site.
It’s simple, yet effective. A lot of times it’s challenging to get
that «perfect balance» between superb usability and visual appearance.
I must say that you’ve done a fantastic job with this.
In addition, the blog loads extremely quick for me on Internet explorer. Superb Blog!
I loved as much as you will receive carried out right here.
The sketch is attractive, your authored subject matter stylish. nonetheless, you command get got an edginess over that you wish be delivering the following. unwell unquestionably come further formerly again since exactly the same nearly a
lot often inside case you shield this increase.
Fantastic web site. Plenty of helpful info here. I am sending
it to some pals ans additionally sharing in delicious. And naturally, thanks to your effort!
hey there and thank you for your information – I’ve definitely picked up anything new from right here. I did however expertise several technical points using this site, as
I experienced to reload the site many times previous to I could get it to load correctly.
I had been wondering if your web host is OK? Not that I am complaining, but sluggish loading
instances times will often affect your placement in google and could damage your high quality score if advertising and marketing
with Adwords. Anyway I am adding this RSS to my email and could look out for a lot more of your respective intriguing content.
Ensure that you update this again soon.
Hi colleagues, fastidious paragraph and good urging commented here, I am genuinely enjoying by these. Also visit my web-site; mink lash extensions london
This piece of writing is truly a good one it assists
new net viewers, who are wishing in favor of blogging.
Just want to say your article is as surprising. The clarity
in your post is simply nice and i could assume you’re an expert on this
subject. Fine with your permission let me to grab your RSS feed to keep up to date with forthcoming post. Thanks a million and please keep up the gratifying work. my website … cs go awp skins steam
I’m amazed, I must say. Rarely do I come across a blog that’s both educative
and amusing, and let me tell you, you’ve hit the nail on the head.
The problem is something that too few men and women are speaking intelligently about.
Now i’m very happy I stumbled across this in my hunt for something regarding this. Here is my website madden mobile coin quick sell (http://www.topstayathomejobs.com)
If some one wants expert view regarding blogging and site-building then i propose him/her to
pay a visit this weblog, Keep up the fastidious job. Feel free to visit my blog post; faux mink eyelash extensions for sale
It’s really a great and helpful piece of info. I’m glad that you shared this helpful info
with us. Please stay us informed like this. Thank you for sharing. Also visit my web site: spending time (Shawnee)
Hi are using WordPress for your blog platform? I’m new to the blog world but I’m trying
to get started and set up my own. Do you need any html
coding expertise to make your own blog? Any help would be really appreciated! Also visit my blog post … fifa 17 coins ps4 mmoga
Very shortly this site will be famous among all blog visitors,
due to it’s nice content Here is my website :: mink eyelash extensions cruelty
I just could not leave your website prior to suggesting that I really enjoyed the usual info an individual supply on your guests? Is gonna be again frequently to inspect new posts my weblog :: cs go steam skins download
magnificent post, very informative. I’m wondering why the other specialists of this sector don’t notice this.
You must continue your writing. I am sure, you’ve a great readers’ base already!
Hi there i am kavin, its my first time to commenting anyplace, when i read this article
i thought i could also make comment due to this good post. Feel free to visit my web-site cs go skins trade site
When I originally commented I clicked the «Notify me when new comments are added» checkbox and now each time a
comment is added I get four emails with the same comment. Is there any way you can remove me from that service? Thank you! my weblog: mink lash extensions vs. synthetic
I don’t even know how I ended up here, but I thought this post was good.
I don’t know who you are but definitely you’re going to
a famous blogger if you aren’t already Cheers! Here is my blog :: fifa 17 coins cheap xbox one
Howdy fantastic blog! Does running a blog like this require a great deal of work?
I have no expertise in programming but I had been hoping to start my own blog soon. Anyway, if
you have any ideas or techniques for new blog owners please share. I know this is off subject but I simply had to ask.
Cheers!
WOW just what I was looking for. Came here by searching for free dating sites
no fees
Why viewers still use to read news papers when in this technological world
the whole thing is presented on net?
I love reading through a post that can make people think.
Also, thank you for allowing for me to comment! Here is my homepage; fifa 17 coins cheap comfort trade (residence-des-sources.com)
It is in reality a nice and useful piece of information. I’m
glad that you simply shared this helpful info with us. Please keep us up to date like this. Thanks for
sharing. Have a look at my blog; cs go steam skins download
It’s awesome in support of me to have a website, which is useful in favor
of my knowledge. thanks admin Have a look at my web-site: mink lashes sephora (http://www.l2ma2.fr)
When I originally left a comment I seem to have clicked on the
-Notify me when new comments are added- checkbox and now whenever a comment
is added I receive 4 emails with the exact same comment.
Perhaps there is a means you are able to remove me from that service? Many thanks!
It’s very easy to find out any topic on web
as compared to textbooks, as I found this post at this web page.
Remarkable! Its actually awesome article, I have got much
clear idea concerning from this post.
When someone writes an article he/she maintains the image of a user
in his/her mind that how a user can know it. Thus that’s why this paragraph is great.
Thanks!
Every weekend i used to pay a visit this web page, as i want enjoyment, as
this this web page conations actually fastidious funny material too.
Hello it’s me, I am also visiting this website daily, this website is actually pleasant and the people are really sharing fastidious thoughts.
Hello!
Hi, I do believe your website may be having web browser compatibility issues. When I look at your site in Safari, it looks fine however when opening in Internet Explorer, it’s got some overlapping issues.
I just wanted to give you a quick heads up! Besides that, great site! my site — silk lash extensions melbourne
Thanks for sharing your thoughts on madden mobile coins no survey no download.
Regards Check out my site … madden mobile coin generator apk
Highly descriptive post, I enjoyed that bit. Will there be a
part 2? Feel free to visit my web page; csgo skins for sale paypal (autopecas-cab.pt)
I like the helpful information you provide in your articles.
I will bookmark your blog and check again here frequently.
I’m quite sure I’ll learn plenty of new stuff right here!
Best of luck for the next!
This post is invaluable. Where can I find out more?
I think this is one of the most important information for me.
And i’m glad reading your article. But wanna remark on few general things,
The web site style is great, the articles is really great :
D. Good job, cheers Here is my website :: madden mobile coin quick sell
There’s certainly a great deal to learn about this issue.
I really like all the points you have made. My webpage; cs go skins trade site (Rachelle)
I’m now not sure where you’re getting your info,
but great topic. I needs to spend some time studying more or figuring out more. Thanks for wonderful info I used to be looking for this information for my mission. Stop by my web blog :: mink lashes starter kit, zarkstudios.com,

Оставить отзыв

Жёлтые поля обязательны к заполнению

   

Можете использовать теги <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang=""> <div class=""> <span class=""> <br>