关于评估顺序的主题说,在C++ 17之前,以下代码会导致未定义的行为:
a[i] = i++;
Run Code Online (Sandbox Code Playgroud)
这是由于在评估赋值表达式的左右部分时未指定的顺序而发生的.
C++ 14标准1.9/15说:
如果对标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值进行的值计算未被排序,并且它们不可能是并发的(1.10),则行为未定义.
但是如果我们使用std::vector它的iterator对象而不是标量对象i呢?
std::vector<int> v = {1, 2};
auto it = v.begin();
*it = *it++; // UB?
Run Code Online (Sandbox Code Playgroud)
是否存在未定义的行为(直到c ++ 17)?
考虑以下代码snipet:
#include <iostream>
struct S {
~S() { std::cout << "dtor\n"; }
const S& f(int i) const { std::cout << i << "\n"; return *this; }
};
int main() {
const S& s = S();
s.f(2);
}
Run Code Online (Sandbox Code Playgroud)
输出:
2
dtor
Run Code Online (Sandbox Code Playgroud)
即对象的生命周期通过引用扩展,这在Herb的文章中有所解释.
但是,如果我们只更改一行代码并写入:
const S& s = S().f(1);
Run Code Online (Sandbox Code Playgroud)
f(2)对已经被摧毁的物体的召唤:
输出:
1
dtor
2
Run Code Online (Sandbox Code Playgroud)
为什么会这样?是f()的返回值不是一个正确的类型'暂时性’的?
我有以下代码片段:
int i[] = {42, i[0]};
Run Code Online (Sandbox Code Playgroud)
是允许这样的初始化还是导致未定义的行为?
三大编译器(GCC,铛,MSVC)给我42的i[1].因此看起来合法,但我希望从这个案例的标准中看到一个引用.
在下面的代码中
struct S {
operator auto() { return 42; }
};
Run Code Online (Sandbox Code Playgroud)
operator auto等价于operator int因为实际类型是从文字中推导出来的,42而该类型是int. 如果我写42.5而不是42thenoperator auto将被解释operator double为显而易见的原因。但是当我同时使用两者时,所有三个主要编译器(gcc、clang、msvc)都出现编译器错误:
struct S {
operator auto() { return 42; }
operator auto() { return 42.5; }
};
Run Code Online (Sandbox Code Playgroud)
编译器之间的实际错误消息各不相同,但原因是相同的:“函数已经定义”。
我无法在标准中找到为什么operator auto不能在一个类中同时使用两者(具有不同的返回类型)。有人可以指出标准的条款,其中该组转换函数被认为是被禁止的吗?
以下代码编译得很好:
struct B {
B(int) {}
};
struct D : B {
D() = default;
};
Run Code Online (Sandbox Code Playgroud)
直到我必须创建一个类的实例D:
D d; // error: use of deleted function 'D::D()'
Run Code Online (Sandbox Code Playgroud)
没有任何理由(用例),以允许= default进行D的构造,当它的实际工作为= delete;?
我试图构建vector的string_view距离Sinitializer_list< const char * >这对GCC 9效果不错,但更新至GCC 10后,在运行时崩溃。
#include <vector>
#include <string_view>
#include <cstdio>
int main()
{
std::vector< std::string_view > const v { { "Before.", "Afterrrrrr." } };
printf( "%s %zu\n", v[0].data(), v[0].length() );
printf( "%s %zu\n", v[1].data(), v[1].length() );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Clang 也处理代码,好吧,什么给出了?
考虑以下代码:
struct NonMovable {
NonMovable() = default;
NonMovable(const NonMovable&) = default;
NonMovable(NonMovable&&) = delete;
};
NonMovable f() {
NonMovable nonMovable;
return {nonMovable};
//return NonMovable(nonMovable);
}
int main() {}
Run Code Online (Sandbox Code Playgroud)
GCC 和 Clang 编译该代码没有错误,即在使用大括号时调用了复制构造函数。但是 msvc 拒绝它https://godbolt.org/z/49onKj并出现错误:
Run Code Online (Sandbox Code Playgroud)error C2280: 'NonMovable::NonMovable(NonMovable &&)': attempting to reference a deleted function
当我指定显式调用复制构造函数(因为nonMovable不是右值)时,mvsc 接受代码。
谁是对的?在return {var};那里的语句中应该调用什么类型的构造函数?
以下代码在 trunk gcc 和 clang 中编译良好,但在 msvc for c++20 模式下编译失败:
template <typename T = int>
void f(void* ptr, T&& t = {}) {
if (ptr) {
f(nullptr);
}
}
Run Code Online (Sandbox Code Playgroud)
与消息:
Run Code Online (Sandbox Code Playgroud)error C2672: 'f': no matching overloaded function found note: could be 'void f(void *,T &&)' note: 'void f(void *,T &&)': could not deduce template argument for 'T' note: 'f': function declaration must be available as none of the arguments depend on a template parameter
适用于 c++17 模式的 msvc,因为 …
我可以使用SFINAE(或其他技术)进行using声明,而私有派生自模板类吗?为了更好地理解,请参阅以下代
#include <iostream>
struct S1 {
void f() { std::cout << "S1::f\n"; }
};
struct S2 {
void f() { std::cout << "S2::f\n"; }
void g() { std::cout << "S2::g\n"; }
};
template <class T>
struct D : private T {
using T::f;
// using T::g; // need this only if T provides g() function
};
int main() {
D<S1>().f(); // ok. Prints 'S1::f'
D<S2>().f(); // ok. Prints 'S2::f'
D<S2>().g(); // fail. But wants to be ok and …Run Code Online (Sandbox Code Playgroud) 我想用clang-format格式化代码,并完整保留lambda用作中间函数参数:
void f()
{
func(this, [this] { return false; }, this);
}
Run Code Online (Sandbox Code Playgroud)
我尝试用clang格式9.0进行的所有操作都将参数包装到下一行,即:
void f()
{
func(
this, [this] { return false; }, this);
}
Run Code Online (Sandbox Code Playgroud)
如果没有第一个或/和最后一个参数,则即使内置-style='WebKit'选项也可以提供所需的结果:
void f()
{
func([this] { return false; }, this); // ok
func(this, [this] { return false; }); // ok
func([this] { return false; }); // ok
}
Run Code Online (Sandbox Code Playgroud)
自LLVM 8.0起,似乎有所更改(损坏),因为7.1可根据需要工作。