小编cur*_*guy的帖子

为什么编译器更喜欢f(const void*)到f(const std :: string&)?

考虑以下代码:

#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

46
推荐指数
1
解决办法
1261
查看次数

std :: atomic <std :: string>是否正常工作?

我正在阅读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)

这是一个未定义的行为,恰好按预期行事吗?

提前致谢!

c++ atomic stdstring stdatomic

44
推荐指数
2
解决办法
2万
查看次数

模板方法的未定义引用错误

这让我疯狂了一个半小时.我知道这是一件小事,但找不到什么是错的(事实上,这是一个下雨的星期五下午,当然,没有帮助).

我已经定义了以下类,它将保存从文件中读取的配置参数,并允许我从我的程序中访问它们:

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)

c++ linker templates compilation

43
推荐指数
3
解决办法
3万
查看次数

关于putenv()和setenv()的问题

我一直在考虑环境变量,并有一些问题/观察.

  • putenv(char *string);

    这个电话似乎有致命的缺陷.因为它不复制传递的字符串,所以无法使用本地调用它,并且无法保证堆分配的字符串不会被覆盖或意外删除.此外(尽管我还没有测试过),因为环境变量的一个用途是将值传递给子环境,如果子进程调用其中一个exec*()函数,这似乎没用.我错了吗?

  • Linux手册页指出glibc 2.0-2.1.1放弃了上述行为并开始复制字符串,但这导致了glibc 2.1.2中修复的内存泄漏.我不清楚这个内存泄漏是什么或它是如何修复的.

  • setenv()复制字符串,但我不确切知道它是如何工作的.当进程加载但是它被修复时,将分配环境空间.这里有一些(任意?)惯例吗?例如,在env字符串指针数组中分配比当前使用的更多的插槽,并根据需要向下移动空终止指针?是否在环境本身的地址空间中分配了新的(复制的)字符串的内存,如果它太大而不适合您只需获得ENOMEM?

  • 考虑到上述问题,有什么理由,更喜欢putenv()setenv()

c unix linux environment-variables setenv

38
推荐指数
3
解决办法
2万
查看次数

C ++-使用const引用来延长临时成员,确定成员或UB成员?

考虑这样的事情:

#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++ temporary lifetime language-lawyer reference-binding

37
推荐指数
1
解决办法
1072
查看次数

显式默认构造函数的用途

我最近注意到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++ explicit explicit-constructor default-constructor

36
推荐指数
2
解决办法
1万
查看次数

在C++中修改constexpr函数中的全局变量17

在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

哪个编译器正确?

c++ language-lawyer constexpr c++17

36
推荐指数
1
解决办法
1512
查看次数

在模板化派生类中,为什么我需要在成员函数中使用"this->"限定基类成员名称?

当我调查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)

c++ qt templates this name-lookup

35
推荐指数
1
解决办法
2660
查看次数

gcc,严格别名,并通过联合进行转换

你有任何恐怖故事要讲吗?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)

c gcc type-conversion strict-aliasing unions

34
推荐指数
3
解决办法
1万
查看次数

将unique_ptr移至lambda时,为什么无法调用reset?

当移动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)
  1. 为什么会这样?
  2. 是否可以通过std::unique_ptr允许reset()在lambda(使用C ++ 17或更高版本)中调用的另一种方式捕获?

c++ lambda unique-ptr c++11 capture-list

34
推荐指数
4
解决办法
1632
查看次数