考虑以下代码:
#include <iostream>
#include <string>
// void f(const char *) { std::cout << "const char *"; } // <-- comment on purpose
void f(const std::string &) { std::cout << "const std::string &"; }
void f(const void *) { std::cout << "const void *"; }
int main()
{
f("hello");
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我编译了这个程序g++ (Ubuntu 6.5.0-1ubuntu1~16.04) 6.5.0 20181026:
$ g++ -std=c++11 strings_1.cpp -Wall
$ ./a.out
const void *
Run Code Online (Sandbox Code Playgroud)
请注意,注释是为了测试而存在,否则编译器使用f(const char *).
那么,为什么编译器会f(const void*)接管f(const std::string …
c++ overloading stdstring string-literals overload-resolution
我正在阅读Anthony Williams的"行动中的C++并发"和第5章,其中讨论了新的多线程感知内存模型和原子操作,并指出:
为了
std::atomic<UDT>用于某些用户定义的UDT类型,此类型必须具有普通的复制赋值运算符.
据我了解,这意味着std::atomic<UDT>如果以下内容返回true ,我们可以使用:
std::is_trivially_copyable<UDT>::value
Run Code Online (Sandbox Code Playgroud)
通过这种逻辑,我们不应该使用它std::string作为模板参数std::atomic并使其正常工作.
但是,以下代码使用预期输出进行编译和运行:
#include <atomic>
#include <thread>
#include <iostream>
#include <string>
int main()
{
std::atomic<std::string> atomicString;
atomicString.store( "TestString1" );
std::cout << atomicString.load() << std::endl;
atomicString.store( "TestString2" );
std::cout << atomicString.load() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是一个未定义的行为,恰好按预期行事吗?
提前致谢!
这让我疯狂了一个半小时.我知道这是一件小事,但找不到什么是错的(事实上,这是一个下雨的星期五下午,当然,没有帮助).
我已经定义了以下类,它将保存从文件中读取的配置参数,并允许我从我的程序中访问它们:
class VAConfig {
friend std::ostream& operator<<( std::ostream& lhs, const VAConfig& rhs);
private:
VAConfig();
static std::string configFilename;
static VAConfig* pConfigInstance;
static TiXmlDocument* pXmlDoc;
std::map<std::string, std::string> valueHash;
public:
static VAConfig* getInstance();
static void setConfigFileName( std::string& filename ) { configFilename = filename; }
virtual ~VAConfig();
void readParameterSet( std::string parameterGroupName );
template<typename T> T readParameter( const std::string parameterName );
template<typename T> T convert( const std::string& value );
};
Run Code Online (Sandbox Code Playgroud)
其中方法convert()定义VAConfig.cpp为
template <typename T>
T VAConfig::convert( const std::string& value ) …Run Code Online (Sandbox Code Playgroud) 我一直在考虑环境变量,并有一些问题/观察.
putenv(char *string);
这个电话似乎有致命的缺陷.因为它不复制传递的字符串,所以无法使用本地调用它,并且无法保证堆分配的字符串不会被覆盖或意外删除.此外(尽管我还没有测试过),因为环境变量的一个用途是将值传递给子环境,如果子进程调用其中一个exec*()函数,这似乎没用.我错了吗?
Linux手册页指出glibc 2.0-2.1.1放弃了上述行为并开始复制字符串,但这导致了glibc 2.1.2中修复的内存泄漏.我不清楚这个内存泄漏是什么或它是如何修复的.
setenv()复制字符串,但我不确切知道它是如何工作的.当进程加载但是它被修复时,将分配环境空间.这里有一些(任意?)惯例吗?例如,在env字符串指针数组中分配比当前使用的更多的插槽,并根据需要向下移动空终止指针?是否在环境本身的地址空间中分配了新的(复制的)字符串的内存,如果它太大而不适合您只需获得ENOMEM?
考虑到上述问题,有什么理由,更喜欢putenv()过setenv()?
考虑这样的事情:
#include <iostream>
struct C {
C(double x=0, double y=0): x(x) , y(y) {
std::cout << "C ctor " << x << " " <<y << " " << "\n";
}
double x, y;
};
struct B {
B(double x=0, double y=0): x(x), y(y) {}
double x, y;
};
struct A {
B b[12];
A() {
b[2] = B(2.5, 14);
b[4] = B(56.32,11.99);
}
};
int main() {
const B& b = A().b[4];
C c(b.x, b.y);
}
Run Code Online (Sandbox Code Playgroud)
当我用-O0编译时,我得到了打印
C ctor …Run Code Online (Sandbox Code Playgroud) 我最近注意到C++ 0x中的一个类需要一个显式的默认构造函数.但是,我没有想出一个可以隐式调用默认构造函数的场景.这似乎是一个相当无意义的说明者.我想也许它会Class c;不赞成,Class c = Class();但似乎并非如此.
来自C++ 0x FCD的一些相关引用,因为我更容易导航[类似文本存在于C++ 03中,如果不在同一个地方]
12.3.1.3 [class.conv.ctor]
默认构造函数可以是显式构造函数; 这样的构造函数将用于执行默认初始化或值初始化(8.5).
它继续提供显式默认构造函数的示例,但它只是模仿我上面提供的示例.
8.5.6 [decl.init]
默认初始化T类型的对象意味着:
- 如果T是一个(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
8.5.7 [decl.init]
对值类型T的对象进行值初始化意味着:
- 如果T是具有用户提供的构造函数(12.1)的(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化是错误的);
在这两种情况下,标准都要求调用默认构造函数.但是如果默认构造函数是非显式的,那就会发生这种情况.为了完整起见:
8.5.11 [decl.init]
如果没有为对象指定初始化程序,则默认初始化该对象;
据我所知,这只是从没有数据的转换.这没有意义.我能想到的最好的是以下内容:
void function(Class c);
int main() {
function(); //implicitly convert from no parameter to a single parameter
}
Run Code Online (Sandbox Code Playgroud)
但显然这不是C++处理默认参数的方式.还有什么会使explicit Class();行为与众不同Class();?
生成此问题的具体示例是std::function[20.8.14.2 func.wrap.func].它需要几个转换构造函数,其中没有一个被标记为显式,但默认构造函数是.
在C++ 17中,您是否可以修改constexpr函数中的全局变量?
#include <iostream>
int global = 0;
constexpr int Foo(bool arg) {
if (arg) {
return 1;
}
return global++;
}
int main() {
std::cout << global;
Foo(true);
std::cout << global;
Foo(false);
std::cout << global;
}
Run Code Online (Sandbox Code Playgroud)
我不希望你能够,但clang 6允许它:https://godbolt.org/g/UB8iK2
但是,海湾合作委员会不会:https://godbolt.org/g/ykAJMA
哪个编译器正确?
当我调查Qt的源代码时,我发现trolltech的人明确使用this关键字来访问析构函数中的字段.
inline ~QScopedPointer()
{
T *oldD = this->d;
Cleanup::cleanup(oldD);
this->d = 0;
}
Run Code Online (Sandbox Code Playgroud)
那么,这个用法有什么意义呢?有什么好处吗?
编辑:对于那些投票支持关闭此问题的人,我怀疑这种用法适用于某些类继承案例
QScopedPointer类定义的一部分:
template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer
Run Code Online (Sandbox Code Playgroud) 你有任何恐怖故事要讲吗?GCC手册最近添加了一个关于-fstrict-aliasing的警告并通过联合转换指针:
[...]获取地址,强制生成指针并取消引用结果具有未定义的行为 [强调添加],即使转换使用了联合类型,例如:
union a_union {
int i;
double d;
};
int f() {
double d = 3.0;
return ((union a_union *)&d)->i;
}
Run Code Online (Sandbox Code Playgroud)
有没有人有一个例子来说明这种未定义的行为?
请注意,这个问题不是关于C99标准所说或不说的.它是关于gcc和其他现有编译器的实际功能.
我只是猜测,但一个潜在的问题可能在于设置d为3.0.因为d是永远不会直接读取的临时变量,并且永远不会通过"稍微兼容"的指针读取,所以编译器可能不会费心去设置它.然后f()将从堆栈中返回一些垃圾.
我的简单,天真,尝试失败了.例如:
#include <stdio.h>
union a_union {
int i;
double d;
};
int f1(void) {
union a_union t;
t.d = 3333333.0;
return t.i; // gcc manual: 'type-punning is allowed, provided...' (C90 6.3.2.3)
}
int f2(void) {
double d = 3333333.0;
return ((union a_union *)&d)->i; // gcc …Run Code Online (Sandbox Code Playgroud) 当移动std::unique_ptr到拉姆达,这是不可能的调用reset()就可以了,因为它似乎是常量,则:
error C2662: void std::unique_ptr<int,std::default_delete<_Ty>>::reset(int *) noexcept': cannot convert 'this' pointer from 'const std::unique_ptr<int,std::default_delete<_Ty>>' to 'std::unique_ptr<int,std::default_delete<_Ty>> &
Run Code Online (Sandbox Code Playgroud)
#include <memory>
int main()
{
auto u = std::unique_ptr<int>();
auto l = [v = std::move(u)]{
v.reset(); // this doesn't compile
};
}
Run Code Online (Sandbox Code Playgroud)
std::unique_ptr允许reset()在lambda(使用C ++ 17或更高版本)中调用的另一种方式捕获?