gpt4 book ai didi

c++ - 为什么我不能用统一初始化来初始化一个字符串?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:21:39 25 4
gpt4 key购买 nike

我有一个模拟窗口的程序;所以我将窗口的内容存储在成员数据 content 中,它是 std::string 类型:

class Window {
using type_ui = unsigned int;
public:
Window() = default;
Window(type_ui, type_ui, char);
void print()const;

private:
type_ui width_{};
type_ui height_{};
char fill_{};
std::string content_{};
mutable type_ui time_{};
};

Window::Window(type_ui width, type_ui height, char fill) :
width_{ width }, height_{ height }, fill_{ fill },
content_{ width * height, fill } { // compile-time error here?
//content( width * height, fill ) // works ok
}

void Window::print()const {
while (1) {
time_++;
for (type_ui i{}; i != width_; ++i) {
for (type_ui j{}; j != height_; ++j)
std::cout << fill_;
std::cout << std::endl;
}
_sleep(1000);
std::system("cls");
if (time_ > 10)
return;
}
}


int main(int argc, char* argv[]) {

Window main{ 15, 25, '*' };
main.print();

std::string str{5u, '*'}; // compiles but not OK
std::string str2(5u, '*'); // compiles and OK
cout << str << endl; // ♣* (not intended)
cout << str2 << endl; // ***** (ok)

std::cout << std::endl;
}

正如您在上面看到的那样,我无法使用 curly-braces-initializer-list 初始化成员 content,编译器会提示“缩小类型”。但它适用于“直接初始化”。

  • 为什么我不能在 Constructor-initializer-list 中使用上面的 Curly-brace-initialization-list 来调用 std::string(size_t count, char)

  • 为什么这个 std::string str{5u, '*'};//编译但不正常 工作但给出的输出不是预期的?

  • 对我来说很重要的事情是,为什么相同的初始化在构造函数成员初始化列表中不起作用,但在 main 中起作用(结果不是预期的)?

最佳答案

  • 首先,因为 std::string的构造函数 sts::string(size_t count, char)是显式的,因此您不能隐式调用它。

  • 其次,您没有调用 std::string(size_t, char)content{width * height, fill}但实际上你正在调用 std::string(std::initializer_list<char>) .因此表达式 width * height产生一个 unsigned int 然后隐式转换为 char 这是“相关类型”因此例如你通过了 Window main{ 15, 25, '*' };哪个产量 (char)15 * 25 = (char)375这是未定义的行为,因为此值溢出 signed char .你可能会在你的机器上得到“♣”或其他值作为初始化列表中的第一个元素但它是未定义的行为并且“”作为初始化列表中的第二个元素。因此,您传递的是 std::initializer_list{'♣', ''}。

    • 只要调用具有多个参数的显式构造函数,就使用直接初始化。
  • 第二个问题的答案:“对我来说很重要的事情是为什么相同的初始化不适用于构造函数成员初始化列表但适用于 main(不是预期的结果)?” :

事实上它与“Constructor-member-initializer-list”没有任何关系但实际上考虑一下:

    char c{ 127 }; // the maximum integer positive value that a signed char can hold so no narrowing conversion here. So it is OK.

char c2{ 128 }; // Now 128 overflows the variavle c2. c2 is of type char and as you know it can hold positive values in range 0 to 127 and negative -1 to -128
unsigned char uc{ 255 }; // ok because an unsigned char can hold 255
unsigned char uc2{ 300 }; // error as the error above. An unsigned char can hold 255 as max positive value.

unsigned char uc3 = 321; // ok // ok but you may get a warning. a Copy-initialization is not safe.
cout << uc3 << endl; // you may get `A`. 321 % 256 = 65. 65 % 256 = 65. 65 in ASCII in some implementations it represents the character "A".

虽然上面的uc3溢出不是什么好事,但是结果是明确的。 (溢出未签名的 Xtype)。

  • 但是看看这个:

    char c3 = 321; // signed char overflows
    cout << c3 << endl; // you may get "A" and think it is correct.

在它上面是未定义的行为。永远不要尝试溢出签名类型。

constexpr int i = 10;
constexpr int j = 5;
std::string str{ i * j, 'f' }; // ok as long as the values are constexpr and don't cause any narrowing conversion this value: 10 * 5 = 50 which is a well defined signed-char value.

int i = 10;
int j = 5;
std::string str{ i * j, 'f' }; // error. the values of i and j are not constant thus it may overflow a signed char causing narrowing conversion thus the compiler is wise enough to prevent this initialization.

关于c++ - 为什么我不能用统一初始化来初始化一个字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55884699/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com