请考虑以下代码:
class A {
public:
int i;
A() {}
};
class B {
public:
A a;
int i;
};
int main() {
B* p = new B {};
std::cout << p->i << " " << p->a.i << "\n";
}
Run Code Online (Sandbox Code Playgroud)
在clang ++中用-std = c ++ 11编译,p->i结果为零,但p->a.i没有.只要它的类没有用户提供的构造函数,整个对象是否应该归零?
编辑:由于评论中有一些广泛的讨论,我认为最好从标准中添加一些摘录:
对值初始化类型的对象
T意味着:
- 如果
T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);- 如果
T是没有用户提供的构造函数的(可能是cv限定的)非联合类类型,则该对象是零初始化的,如果T隐式声明的默认构造函数是非平凡的,则调用该构造函数.- 如果
T是数组类型,则每个元素都是值初始化的;- 否则,该对象被零初始化.
零初始化T类型的对象或引用意味着:
- 如果
T是标量类型(3.9),则将对象设置为值0(零),作为整数常量表达式,转换为T;- 如果
T是(可能是cv限定的)非联合类类型,则每个非静态数据成员和每个基类子对象都是零初始化的,并且填充初始化为零位;- if
T …
friend函数f无权访问封闭类的私有成员A.
#include <iostream>
class A{
const static int p = 1;
class B {
friend void f() {
std::cout << p << '\n';
std::cout << q << '\n';
}
};
public:
const static int q = 2;
};
void f();
int main()
{
f();
}
Run Code Online (Sandbox Code Playgroud)
至少,这是我认为N4140中的[class.nest]/4所说的(见下文).
§9.7/ 4
与成员函数一样,嵌套类中定义的友元函数(11.3)位于该类的词法范围内; 它遵循与名称绑定相同的规则作为该类的静态成员函数(9.4),但它对封闭类的成员没有特殊的访问权限.
g ++ 4.8.1和clang ++ 3.4为下一个代码提供了不同的结果:
// simplified code from a Logger module
#include <iostream>
template<class T> void tf(const T*) { // clang++
std::cout << "void tf(const T*)\n";
}
template<class T> void tf(T) { // g++
std::cout << "void tf(T)\n";
}
int main(){
typedef std::ios_base& (*ph)(std::ios_base&);
ph p = std::hex;
tf(p); // or just tf(std::hex)
}
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚哪个变体是正确的(C++ 03).
下面的代码不是在clang下编译但是在gcc和VS下编译:
template<typename T> class bar;
namespace NS
{
template<typename T>
class foo
{
foo() {}
template<typename U> friend class bar;
};
}
template<typename R>
class bar
{
public:
bar()
{
NS::foo<int> f;
}
};
int main(int, char **)
{
bar<int> b;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它失败了:
main.cpp:20:22: error: calling a private constructor of class 'NS::foo<int>'
NS::foo<int> f;
^
main.cpp:8:9: note: implicitly declared private here
foo() {}
^
Run Code Online (Sandbox Code Playgroud)
bar应该有权访问foo私有构造函数但看起来却没有.如果我删除namespace NS,它编译.
代码看起来很好,但也许我误解了C++标准.哪个编译器正确?
为什么这个代码用GCC(4.9和5+)编译,而不是用clang(3.5-3.9)编译?
void test(const int&) { }
int main() {
const int x = 42;
auto f = []{ test(x); };
}
Run Code Online (Sandbox Code Playgroud)
我有一些模糊的想法,认为这种差异与ODR(一种定义规则)的使用有关,但我不太了解这一点,以便弄清楚这里发生了什么.
我编译了以下c++程序:
int main() { 2==3; }
Run Code Online (Sandbox Code Playgroud)
和:
clang++-5.0 -std=c++17 -Wunused-comparison prog.cpp
Run Code Online (Sandbox Code Playgroud)
并收到警告:
warning: equality comparison result unused [-Wunused-comparison]
2==3;
~^~~
Run Code Online (Sandbox Code Playgroud)
...所以,这可能不是在 CLANG 中抑制警告的正确方法。
在clang 手册中,这部分是“TODO”。
禁用警告的正确命令行标志是什么?
我有以下示例代码,简化为必需的,编译与gcc 6.1,gcc 7.0 head和Visual Studio 2015/2017RC,但没有任何clang版本.
#include <iostream>
#include <tuple>
using namespace std;
namespace outer {
namespace test {
template <typename A, typename B, typename...C>
auto bar_(A&&, B&&, C&&... c) {
return std::make_tuple(c._p...);
}
}
template <typename A, typename B, typename...C>
auto bar(A a, B b, C&&... c) {
return test::bar_(std::move(a), std::move(b), std::forward<C>(c)...);
}
template<typename T>
class foo
{
template <typename A, typename B, typename...C>
friend auto test::bar_(A&&, B&&, C&&... c);
int _p;
public:
foo(int f) : _p(f) {}
}; …Run Code Online (Sandbox Code Playgroud) 我刚刚在clang和gcc之间遇到了一个奇怪的区别,我想编译看起来类似于以下内容的代码:
namespace n1 {
template <class T1, class T2>
struct MyTemplate {
struct Inner {};
};
}
using namespace n1;
namespace n2 {
using MyClass = MyTemplate<int, int>;
}
namespace n1 {
using n2::MyClass;
template<> struct MyClass::Inner {
int member;
};
MyClass::Inner inner{0};
}
Run Code Online (Sandbox Code Playgroud)
Clang愉快地编写了这个:
$ clang++ -std=c++11 -c -o alias_specialization.o alias_specialization.cc
Run Code Online (Sandbox Code Playgroud)
但是gcc会抛出以下错误:
$ g++ -std=c++11 -c -o alias_specialization.o alias_specialization.cc
alias_specialization:15:30: error: declaration of ‘struct n1::MyTemplate<int, int>::Inner’ in namespace ‘n1’ which does not enclose ‘using MyClass = struct n1::MyTemplate<int, int>’ …Run Code Online (Sandbox Code Playgroud) 尝试打印第一个命令行参数时:
std::cout << argv[0] << std::endl;
Run Code Online (Sandbox Code Playgroud)
clang-tidy发出警告:
警告:[cppcoreguidelines-pro-bounds-pointer-arithmetic]中的'不使用指针运算'
有argv没有使用指针算法的替代方法来使用值?是不是char**通过任何明智的方法访问必须使用指针算术?
我欣赏有一些专门的函数来处理命令行参数,但它们似乎太重了,不能简单地打印一个参数.
我正在编写c++,使用clang编译器和构建cmake.
c++ pointer-arithmetic command-line-arguments clang-static-analyzer clang++
给出以下源代码:
#include <memory>
#include <typeinfo>
struct Base {
virtual ~Base();
};
struct Derived : Base { };
int main() {
std::unique_ptr<Base> ptr_foo = std::make_unique<Derived>();
typeid(*ptr_foo).name();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并编译它:
clang++ -std=c++14 -Wall -Wextra -Werror -Wpedantic -g -o test test.cpp
环境设置:
linux x86_64
clang version 5.0.0
Run Code Online (Sandbox Code Playgroud)
由于警告(注释-Werror)它不编译:
error: expression with side effects will be evaluated
despite being used as an operand to 'typeid'
[-Werror,-Wpotentially-evaluated-expression]
typeid(*ptr_foo).name();
Run Code Online (Sandbox Code Playgroud)
(请注意:海湾合作委员会并未声称存在这种潜在问题)
题
有没有办法获得有关a指向的类型的信息unique_ptr而不产生那种警告?
注意:我不是在谈论禁用-Wpotentially-evaluated-expression或避免-Werror.