スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C++の知らなかったこと。

C++の知らなかった機能(規格)をひたすら列挙していきます。



char* str =
"line1"
"line2"
"line3";

これで"line1line2line3"という文字列になる。
もちろんstd::stringでもできます。
const char* STR = "line2";
char* str =
"line1"
STR
"line3";

これは不可、定数であれリテラル以外が絡むとだめらしい。

 恥ずかしいことに今までこうしてました(笑)。
const std::string STR = std::string() +
"line1" +
"line2" +
"line3";

(某中3女子さんありがとうございます!)

こういうのもできるみたい。
std::string str =
"line1\
line2\
line3";

=> "line1line2line3"

なお、これにインデント入れたりすると
std::string str =
"line1\
line2\
line3";

=> "line1 line2 line3"
こうなります…。


ところで、streamのoperator<<もしくはoperator>>以外の関数を呼び出すと、
バッファがおかしくなりません?
std::cout << "please input char: ";
char c = std::cin.get();
std::string str;
std::cout << "please input str: ";
std::cin >> str;
std::cout << "output: " << std::endl
<< c << std::endl
<< str << std::endl;

please input char: aaa
please input str: // スルーされる。
output:
a
aa

っていう。


------------------------------

C++で配列オブジェクト


Cのベターな配列受け渡し方法…こうですね。
void func(int* a, const int len){
int i;
for(i=0; i<len; i++)
a[i] = i;
}
int main(){
const int LEN = 5;
int a[5];
func(a, LEN);
}

こわい。
なにこれ怖いです。
C++11でこんなことをするわけにはいかないのです!!
ってことで…std::vector使っちゃう?
まって!! それ可変長だよ!!

ってことで…ちゃんとC++11なら固定長な配列オブジェクトが用意されていたんですね…。
<tr1/array>ヘッダstd::tr1::array<T,size>です!!
先ほどの例にならって書いてみましょう。
#include <tr1/array>
template <typename T, int size>
void func(std::tr1::array<T,size> a){
for(T i=0; i<size; i++)
a[i] = i;
}
auto main() -> int {
constexpr int LEN = 5;
std::tr1::array<int,LEN> a;
func<int,LEN>(a);
}

C++11きたこれっ!!
------------------------------
スポンサーサイト

ほんの些細な数時間? 「配列は本当にポインタなのか?」の話

 今日、普通にクラス設計を考えていた時のことなのですが、
int a[] = {1,2,3,4,5};
int *b = a;
for(int view : b)
std::cout << view << std::endl;
みたいなことできないかなーと考えていたのですよ。

 なんだかあらゆるどこかで「配列はポインタ」と聞いていたので、
配列変数の持つアドレス普通のポインタに移す
なぜイテレータが削除されているのか!!と。

 先ほどの例で言うと
int a[] = {1,2,3,4,5};
int *b = a;


for(int view : a)
std::cout << view << std::endl;
はできるのに
int a[] = {1,2,3,4,5};
int *b = a;
for(int view : b)
std::cout << view << std::endl;
はできない。
というやつ。


 もっと突き進めてみる。
そもそもあれを実現するにはfor each(拡張for)でなくて
int a[] = {1,2,3,4,5};
int *b = a;
const int LEN = sizeof(b)/sizeof(b[0]);
for(int i=0; i<LEN; i++)
std::cout << b[i] << std::endl;
ができれば十分!

 でもできない。
ということは
「本当に『配列』『ポインタ』等価なのか!?
ということになるのですよ…。

 結論から言うと一部分違いました
解答(?)は以下。
  1 #include 
2 #include
3
4 auto main() -> int {
5 »___int a[] = {1,2,3,4,5};
6 »___int *b = a;
7 »___std::cout << a << std::endl
8 »___»___»___ << b << std::endl
9 »___»___»___ << (a == b) << std::endl
10 »___»___»___ << (sizeof(a) == sizeof(b)) << std::endl
11 »___»___»___ << (typeid(a) == typeid(b)) << std::endl
12 »___»___»___ << typeid(a).name() << " " << typeid(b).name() << std::endl;
13 };


 出力結果はこの通りです。(表記をbool型に変えてあります 1=>true)
0x7fff55b0f320  // aの参照先アドレス
0x7fff55b0f320 // bの参照先アドレス
true // a == b
false // aのbitサイズ != bのbitサイズ
false // aの型 != bの型
A5_i Pi // aの型名, bの型名

A5_iというのは「Array Size[5] Integer」でしょうか。
Piも多分「Pointer Integer」。
試しにaを
int a[] = {1,2,3,4,5,6};
に変えてみると、
typeid(a).name()も「A6_i」に変わりました

ってことはさ…
「『配列』は『ポインタ』」じゃないじゃん!!

配列はポインタとしての扱いも受けますが、イテレータ( begin()やend() )も持ちますよ

ってことですね。


…typeid(a)とtypeid(b)を比較してみる、ということにたどり着くまで結構かかってしまいました……。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。