#2
by かずま » 7年前
keito さんが書きました: ↑7年前
構造体fooをstd::vector<foo>にpush_backしたいのですが、
「"initializer list"から"const foo&"に変換できません」や
「型 "char *"の値を使用して "char"型の実体を初期化はできません」
とコンパイラに怒られてしまいます…。
エラーメッセージを示すときは、行番号も付けてください。
:ch(c), ですが、ch は char[3], c は char * です。
char[3] は、char * では初期化できません。
{ 'a', 'b', '\0' } のような初期化リストなら、char[3] を初期化できます。
pch(new char[3]]{ *p }) では、*p が char であり、その値は
p[0] の 1文字だけです。pch[0] は p[0] で初期化されますが、
pch[1] と pch[2] は 0 に初期化されます。
次に、ポインタをメンバ変数に持つクラスでは、
コピーコンストラクタと代入演算子を定義しないと
おかしなことになります。
push_back() で vector に fooオブジェクトを入れるとき、
コピーコンストラクタが使用されます。
これを定義していないと、ch[0], ch[1], ch[2], pch がコピーされます。
pch[0], pch[1], pch[2] はコピーされません。
pch だけがコピーされると、2つのオブジェクトの pch が同じ領域を指し、
デストラクタで二重に delete されて、問題になります。
また、new[] で確保された領域の解放は、
delete ではなく、delete[] です。
keito さんが書きました: ↑7年前
どうすればエラーが無くなるのでしょうか?
コード:
#include <iostream>
#include <vector> // vector
#include <algorithm> // copy
struct foo {
char ch[3];
char *pch;
foo(const char *c, const char *p) : ch{ c[0], c[1], c[2] },
pch(new char[3] { p[0], p[1], p[2]}) { }
foo(const foo& x) : ch{ x.ch[0], x.ch[1], x.ch[2] },
pch(new char[3] { x.pch[0], x.pch[1], x.pch[2] }) { }
foo& operator=(const foo& x) {
if (&x != this) {
std::copy(x.ch, x.ch + 3, ch);
std::copy(x.pch, x.pch + 3, pch);
}
return *this;
}
~foo() { delete[] pch; }
};
int main()
{
std::vector<foo> v;
char c1[3] = "ab";
const char *c2 = "cd";
v.push_back({ c1, c2 });
v.push_back({ c2, c1 });
std::cout << "{ " << v[0].ch << ", " << v[0].pch << " }\n";
std::cout << "{ " << v[1].ch << ", " << v[1].pch << " }\n";
}
[quote=keito post_id=150320 time=1522049894 user_id=2094]
構造体fooをstd::vector<foo>にpush_backしたいのですが、
「"initializer list"から"const foo&"に変換できません」や
「型 "char *"の値を使用して "char"型の実体を初期化はできません」
とコンパイラに怒られてしまいます…。[/quote]
エラーメッセージを示すときは、行番号も付けてください。
:ch(c), ですが、ch は char[3], c は char * です。
char[3] は、char * では初期化できません。
{ 'a', 'b', '\0' } のような初期化リストなら、char[3] を初期化できます。
pch(new char[3]]{ *p }) では、*p が char であり、その値は
p[0] の 1文字だけです。pch[0] は p[0] で初期化されますが、
pch[1] と pch[2] は 0 に初期化されます。
次に、ポインタをメンバ変数に持つクラスでは、
コピーコンストラクタと代入演算子を定義しないと
おかしなことになります。
push_back() で vector に fooオブジェクトを入れるとき、
コピーコンストラクタが使用されます。
これを定義していないと、ch[0], ch[1], ch[2], pch がコピーされます。
pch[0], pch[1], pch[2] はコピーされません。
pch だけがコピーされると、2つのオブジェクトの pch が同じ領域を指し、
デストラクタで二重に delete されて、問題になります。
また、new[] で確保された領域の解放は、
delete ではなく、delete[] です。
[quote=keito post_id=150320 time=1522049894 user_id=2094]
どうすればエラーが無くなるのでしょうか?[/quote]
[code]
#include <iostream>
#include <vector> // vector
#include <algorithm> // copy
struct foo {
char ch[3];
char *pch;
foo(const char *c, const char *p) : ch{ c[0], c[1], c[2] },
pch(new char[3] { p[0], p[1], p[2]}) { }
foo(const foo& x) : ch{ x.ch[0], x.ch[1], x.ch[2] },
pch(new char[3] { x.pch[0], x.pch[1], x.pch[2] }) { }
foo& operator=(const foo& x) {
if (&x != this) {
std::copy(x.ch, x.ch + 3, ch);
std::copy(x.pch, x.pch + 3, pch);
}
return *this;
}
~foo() { delete[] pch; }
};
int main()
{
std::vector<foo> v;
char c1[3] = "ab";
const char *c2 = "cd";
v.push_back({ c1, c2 });
v.push_back({ c2, c1 });
std::cout << "{ " << v[0].ch << ", " << v[0].pch << " }\n";
std::cout << "{ " << v[1].ch << ", " << v[1].pch << " }\n";
}
[/code]