我是C++初学者,我正在阅读Bjarne Stroustrup的编程:使用C++的原理和实践.
在3.9.2"不安全转换 "一节中,作者提到了
当初始化程序是整数文字时,编译器可以检查实际值并接受不暗示缩小的值:
Run Code Online (Sandbox Code Playgroud)int char b1 {1000}; // error: narrowing (assuming 8-bit chars)
我对这个宣言感到困惑.它使用两种类型(int和char).我以前从未在Java和Swift中看过这样的声明(我比较熟悉的两种语言).这是拼写错误还是有效的C++语法?
c++ initialization type-conversion narrowing uniform-initialization
以下代码:
#include <vector>
struct S
{
    int x, y;
};
int main()
{
    std::vector<S> v;
    v.emplace_back(0, 0);
}
使用GCC编译时出现以下错误:
In file included from c++/4.7.0/i686-pc-linux-gnu/bits/c++allocator.h:34:0,
                 from c++/4.7.0/bits/allocator.h:48,
                 from c++/4.7.0/vector:62,
                 from test.cpp:1:
c++/4.7.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = S; _Args = {int, int}; _Tp = S]':
c++/4.7.0/bits/alloc_traits.h:265:4:   required from 'static typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = S; _Args = {int, int}; _Alloc = std::allocator<S>; typename std::enable_if<std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::value, void>::type = void]'
c++/4.7.0/bits/alloc_traits.h:402:4:   required …注意派生使用C++ 11统一初始化语法来调用基类构造函数.
class base
{
    protected:
        base()
        {}
};
class derived : public base
{
    public:
        derived()
            : base{} // <-- Note the c++11 curly brace syntax
                     // using uniform initialization. Change the
                     // braces to () and it works.
        {}
};
int main()
{
    derived d1;
    return 0;
}
g ++ 4.6编译它,但是g ++ 4.7没有:
$ g++-4.7 -std=c++11 -Wall -Wextra -pedantic curly.cpp -o curly
curly.cpp: In constructor ‘derived::derived()’:
curly.cpp:4:13: error: ‘base::base()’ is protected
curly.cpp:19:24: error: within this context …#include <iostream>
using namespace std;
struct A
{
    A() { cout << "A" << endl; }
    ~A() { cout << "~A" << endl; }
};
A Ok() { return {}; }
A NotOk() { throw "NotOk"; }
struct B
{
    A a1;
    A a2;
};
void f(B) {}
int main()
{
    try
    {
        f({ Ok(), NotOk() });
    }
    catch (...)
    {}
}
vc++并clang输出:
A
~A
虽然gcc产出:
A
这似乎是GCC的一个严重错误.
也就是说,为什么这样:
struct S {};
struct T
{
    T(S& s) : s{s} {}
    S& s;
};
int main()
{
    S s;
    T t{s};
}
给我一个GCC 4.7的编译器错误:
test.cpp: In constructor 'T::T(S&)':
test.cpp:5:18: error: invalid initialization of non-const reference of type 'S&' from an rvalue of type '<brace-enclosed initializer list>'
?
要修复错误,我必须更改s{s}为s(s).这不会打破统一初始化的统一性吗?
编辑:我试过clang,clang接受它,所以也许这是一个GCC错误?
请考虑以下代码段:
#include <iostream>
struct A {
  A() {}
  A(const A&) {}
};
struct B {
  B(const A&) {}
};
void f(const A&) { std::cout << "A" << std::endl; }
void f(const B&) { std::cout << "B" << std::endl; }
int main() {
  A a;
  f(   {a}   ); // A
  f(  {{a}}  ); // ambiguous
  f( {{{a}}} ); // B
  f({{{{a}}}}); // no matching function
}
为什么每个调用都会编写相应的输出?支撑数如何影响均匀初始化?支撑精益如何影响这一切?
c++ language-lawyer uniform-initialization c++11 list-initialization
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct …
显式复制构造函数不允许使用类似的东西Foo foo = bar;,并强制执行复制用法Foo foo(bar);.此外,显式复制构造函数还禁止通过函数的值返回对象.但是,我尝试用大括号替换副本初始化,就像这样
struct Foo
{
    Foo() = default;
    explicit Foo(const Foo&) = default;
};
int main()
{
    Foo bar;
    Foo foo{bar}; // error here
}
我收到了错误(g ++ 5.2)
错误:没有匹配函数来调用'Foo :: Foo(Foo&)'
或(clang ++)
错误:struct initializer中的多余元素
删除explicit使得代码在g ++下可编译,clang ++仍然失败并出现相同的错误(感谢@Steephen).这里发生了什么?统一初始化是否被视为初始化列表构造函数(胜过所有其他构建函数)?但如果是这种情况,为什么程序在复制构造函数非显式时编译?
c++ copy-constructor language-lawyer uniform-initialization c++11
过去几天我一直在玩C++ 11,我想出了一些奇怪的东西.
如果我想统一初始化一个int:
int a{5};
但是如果我对std :: vector做同样的事情:
std::vector<int> b{2};
不构造一个两元素数组,而是一个具有一个值为2的元素的数组.似乎要获得这种效果,需要更加明确它:
std::vector<int> c{{2}};
std::vector<int> d = {2};
但不像b的声明 - 这似乎不一致.我已经看到了其他一些相同的效果.我要问的是 - 这是最终C++ 11标准中的这种行为,还是只是在早期实施的草案中?如果是这样,为什么标准委员会会包含这种行为?看起来它破坏了统一初始化的整个目的,因为必须记住哪些类具有初始化列表构造函数,并且只使用old()语法而不是{}.或者一个人放弃统一初始化.
这似乎是一个很大的"陷阱".但是我不知道它可能有优点.
编辑:此代码:
#include <iostream>
#include <vector>
int main() {
    std::vector<int> a{2};
    for (auto x: a) {
        std::cout << x << std::endl;
    }
    return 0;
}
在gcc 4.6.2上输出"2"
我正在阅读C++ 11标准,但无法弄清楚是否
T x{};
是值初始化或默认初始化(自动存储).它确实说得非常清楚:
10一个对象,其初始化程序是一组空的括号,即(),应进行值初始化.
然后
11如果没有为对象指定初始值设定项,则默认初始化该对象;
但我能找到的T x{};是:
在表格T x(a)中发生的初始化; T x {a}; 以及在新表达式(5.3.4)中,static_cast表达式(5.2.9),函数表示法类型转换(5.2.3)以及基本和成员初始化器(12.6.2)称为直接初始化.
和
如果初始化程序是(非括号的)braced-init-list,则对象或引用是列表初始化的(8.5.4).
我很想进入阅读标准的水平.有人能指出我正确的方向吗?